返回

初学Promise对象

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。该文章按本人学习常用的进行讲解

初学Promise对象,异步基础

  • 推荐实践代码,自己动手调试,更容易理解原理

基础

三个状态(重要)

  • pendding 等待状态
  • fullfilled 完成状态
  • rejected 失败状态

状态流向以及回调函数resolve和reject

Promise状态流向只有两种,而且状态一旦改变,则不会再变

  1. 调用reolve函数,则 pendding => fullfilled
  2. 调用rejecte函数,则pendding => rejected
  3. 只接收第一个参数调用后改变状态,其他的忽略
1
2
3
4
5
6
7
const promise = new Promise((resolve, reject) => {
  resolve(1);
  reject(2); // 被忽略
})
console.log(promise)
// PromiseState : fullfilled
// PromiseResult: 1

消费者 .then、.catch

最重要最基础的一个就是 .then

个人见解就是then就是对Promise对象的一个总结反馈,判断对象的状态并且执行fullfilled后的函数

  • .then 的第一个参数是一个函数,该函数将在 promise resolved 且接收到结果后执行。

  • .then 的第二个参数也是一个函数,该函数将在 promise rejected 且接收到 error 信息后执行。

下面例子,可自己通过注释选择resolve还是reject

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let promise = new Promise(function(resolve, reject) {
  // setTimeout(() => resolve("done!"), 1000);
  setTimeout(() => reject(new Error("Whoops!")), 1000);
});

// reject 运行 .then 中的第二个函数
promise.then(
  result => alert(result), // 不运行
  error => alert(error) // 1 秒后显示 "Error: Whoops!"
);

如果我们只对某个状态的情况感兴趣,那么我们可以只为 .then 提供一个函数参数:

1
2
3
4
5
6
7
let promise = new Promise(resolve => {
  setTimeout(() => resolve("done!"), 1000);
  // setTimeout(() => reject("fail!"), 1000);
});

promise.then(alert); // 1 秒后显示 "done!"
// promise.catch(alert); // 1 秒后显示 "fail!"

实际情况成功的情况较为常见,并且.then和.catch也可以通过链式写法

1
2
3
4
5
new Promise((resolve, reject) => {
  resolve(42);
}).then(value => {
  console.log(value); // 输出: 42
});

Promise.API

await+async

  • Promise 通过链式调用(如 .then() 和 .catch())管理异步操作的成功或失败;
  • async 修饰的函数总会返回一个 Promise,无论返回的是普通值还是 Promise 本身;
  • await await语句之后的代码处于微队列,用于暂停 async 函数的执行,等待后面的 Promise 解析完成,然后直接获得解析结果,从而让异步代码写起来更像同步代码,避免了冗长的 .then() 链。

await 等待的不一定是promise对象,也有可能为await 1; ==> await Promise.resolve(1)

Promise.all

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
Promise.all([
  // 每个数组对象都是**异步微任务**,因此1和2瞬间输出
  // 对象5 需要等待 对象4 await执行完毕后执行,即3秒后输出3
  new Promise(resolve => setTimeout(() => resolve(4), 4000)), // 对象0,value4
  console.log(1), // 对象1,undefined(不是promise对象)
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 对象2,value2
  console.log(2), // 对象3,undefined
  await new Promise(resolve => setTimeout(() => resolve(3), 3000)),  // 对象4,value3
  console.log(3), // 对象5,undefined
]).then((res) => {
  console.log(res);
}) // 4秒后所有异步任务执行完毕,输出
[
    0:1,
    1:undefined,
    2:2,
    3:undefined,
    4:3,
    5:undefined
]

全部完成才会运行.then,如果有某一个失败,则不执行.then

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Promise.allSettled([
  new Promise(resolve => setTimeout(() => resolve(4), 4000)),
  console.log(1),
  new Promise((resolve,reject) => setTimeout(() => reject(2), 2000)), // 这里使用reject
  console.log(2),
  await new Promise(resolve => setTimeout(() => resolve(3), 3000)), 
  console.log(3),
]).then((res) => {
  console.log(res);
})
[
    0:1,
    1:undefined,
    2:2,
    3:undefined,
    4:3,
    5:undefined
]

Promise.allsettled

如果任意的 promise reject,则 Promise.all 整个将会 reject。当我们需要 所有 结果都成功时,它对这种“全有或全无”的情况很有用

Promise.allSettled 等待所有的 promise 都被 settle,无论结果如何。结果数组会是这样的:

  • 对成功的响应,结果数组对应元素的内容为 {status:"fulfilled", value:result}
  • 对出现 error 的响应,结果数组对应元素的内容为 {status:"rejected", reason:error}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Promise.allsettled([
  new Promise(resolve => setTimeout(() => resolve(4), 4000)),
  console.log(1),
  new Promise((resolve,reject) => setTimeout(() => reject(2), 2000)), // 这里使用reject
  console.log(2),
  await new Promise(resolve => setTimeout(() => resolve(3), 3000)), 
  console.log(3),
]).then((res) => {
  console.log(res);
})
// 控制台输出
[
    0:{status:fullfiled,value:4},
    1:{status:fullfiled,value:undefined},
    2:{status:rejected,reson:2},
    3:{status:fullfiled,value:undefined},
    4:{status:fullfiled,value:3},
    5:{status:fullfiled,value:undefined},
]

参考文献

js小红书

ECMAScript 6 入门

一道让我失眠的 Promise 面试题

使用 Hugo 构建
主题 StackJimmy 设计