Day 23 - Promise

Promise 解决了回调地狱,在处理一些需要花费比较长时间的任务时使用 Promise 就可以进行非同步的处理,防止阻塞。

使用方式:
利用 Constructor 制作一个 Promise 物件,且 Promise 会接收一个 function 作为参数,传递给 Promise 的 function 有 resolve 和 reject 参数,resolve 表示成功,reject 表示失败。

// Initialize a promise
const promise = new Promise((resolve, reject) => {})
console.log(promise);

这时候开启 Devtool 可以看到 PromiseState 为 pending(进行中),表示 resolve 或 reject 之前的初始状态,因为我们还没设定 resolve 和 reject 要做啥事。
https://ithelp.ithome.com.tw/upload/images/20210924/20140282MC9JafqCUm.jpg

PromiseState 分为三种:

  • pending - 进行中
  • fulfilled- 操作成功,promise 已解决
  • rejected - 操作失败,promise 被拒绝

将 Promise 展开,可以看到里面有 Promise(), catch(), then(), finally()
https://ithelp.ithome.com.tw/upload/images/20210924/20140282yUOYYqVySU.jpg

  • then() 表示处理 resolve
  • catch() 表示处理 reject
  • finally() 当一个 promise 被解决时调用,无论结果是成功或是失败都会执行。

接着再将 Promise() 这个 constructor 展开,可以发现里面有许多方法,包含了 resolve(),reject(),race(),all()...等。
https://ithelp.ithome.com.tw/upload/images/20210924/20140282gyK7io61JY.jpg

  • Promise.resolve() 作用为将 PromiseState 由 pending 变成 fulfilled
  • Promise.reject() 作用为将 PromiseState 由 pending 变成 rejected
  • Promise.race() 用於处理多个 Promise,只要有一个成功,就 return 成功结果,其他的被淘汰,如果全部失败,就 return 失败
  • Promise.all() 用於处理多个 Promise,如果有其中一个 Promise 失败全部就失败,而全部的 Promise 都成功才代表成功。

来举个简单的例子~

function fn1(){
  setTimeout(function(){
    console.log(1)
  },0)
}
function fn2(){
  console.log(2)
}
fn1()
fn2()
// 2
// 1

setTimeout() 为非同步事件,即使时间设定 0 秒,JavaScript 也会先跳过它,先往下执行别的动作,最後再回来执行它,所以最终的结果会先印出 2 再印出 setTimeout() 里的 1。

如果我们想要结果如同执行 function 的顺序,先印出 fn1() 再印出 fn2(),可以使用 Promise()。

function fn1() {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      console.log(1);
      resolve(); // 这个 resolve 会决定 fn 什麽时候会进 then
    }, 0)
  })
}
function fn2() {
  console.log(2);
}
fn1().then(fn2); // 执行後 console.log 的顺序为 1 => 2
// 1
// 2

再来举个不只一个 Promise 的例子:

const PROMISE1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("PROMISE1");
  },0)
})

const PROMISE2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("PROMISE2");
  },1000)
})

const RES = Promise.race([PROMISE1,PROMISE2]);
console.log(RES)

上面的例子使用 race(),只要有一个成功最终的结果就是成功,而因为 PROMISE1 执行时就 resolve,所以最後 PromiseState 会显示 fulfilled。
https://ithelp.ithome.com.tw/upload/images/20210927/20140282bxC8sGTDNn.jpg

将上面的程序码改一下

const PROMISE1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("PROMISE1");
  },2000)
})

const PROMISE2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("PROMISE2");
  },1000)
})

const RES = Promise.race([PROMISE1,PROMISE2]);
console.log(RES)

因为 PROMISE2 设定的时间比 PROMISE1 短,会先执行 PROMISE2,而 PROMISE2 里面是 reject,所以最後 PromiseState 会显示 rejected,且 PromiseResult 为 PROMISE2。
https://ithelp.ithome.com.tw/upload/images/20210927/20140282dioYXcCKzw.jpg

参考资料:
Promise - MDN
Understanding the Event Loop, Callbacks, Promises, and Async/Await in JavaScript


最後推荐一下不错的资源:


<<:  [Day 09] - Spring Boot 实作登入验证(三)(JWT实作)

>>:  Day24. Blue Prism加班日 –BP自动选定功能

Day7-JDK查看正在运行的Java进程工具:jps

前言 在介绍JDK有哪些工具时,第二大列应该是『故障排查、分析、监控和管理工具』,但我想先从监控工具...

03. Unit Test x PHPUnit x FizzBuzz

Fizz Buzz 是个小朋友的游戏,小朋友们依序报数,但当遇到三的倍数要喊 fizz、五的倍数喊 ...

Day.6 「只要我想,我也能把 div 变 table!」 —— CSS display 属性

如同前面章节所说,一开始的标签元素,很单调只有一行并没有各式各样的元素,是浏览器内建的样式表赋予它...

Day 27 - Vue 与 HTTP请求 (2)

前一天我们对HTTP有了基础的概念,今天就要来谈谈要怎麽在vue中发送HTTP请求。 我们会引用ax...

[Day06] 团队系统设计 - 张力分析

某次参加站立会议,某位 PM 情绪激动的说:「我後天要跟客户回报进度了,但 A 同事这周请假三天,明...