ES6-Promise

Lán2022年11月9日
大约 3 分钟

ES6-Promise

Promise 是异步操作的一种解决方案,一般用来解决层层嵌套的回调函数(回调地狱 callback hell)的问题

Promise 有 3 种状态,一开始是 pending(未完成),执行 resolve,变成 fulfilled(resolved) => 已成功,执行 reject,变成 rejected => 已失败

  • pending 初始化待定状态
  • fulfilled(resolved) 成功解决状态
  • rejected 拒绝状态

Promise 的状态一旦变化,就不会再改变了

then方法

pending->fulfilled 时,执行 then 的第一个回调函数
pending->rejected 时,执行 then 的第二个回调函数

then 方法执行后返回一个新的 Promise 对象
在 then 的回调函数中,return 后面的东西,会用 Promise 包装一下,默认返回的永远都是成功状态的 Promise 对象

new Promise((resolve,reject) => {
   //成功回调给下一个then
   resolve();
}).then(
  () => {
    console.log('success1');
    return new Promise((resolve,reject) => {
      //错误回调给下一个then
      reject();
    })
  },
  () => {
    console.log('err1');
    //默认回调给下一个then是成功,并且return后面的东西会被包装成Promise
    return undefined;
  }
).then(
  () => {
    console.log('success2');
  },
  () => {
    console.log('err2');
  }
);

catch方法

catch 专门用来处理 rejected 状态

catch 本质上是 then 的特例: then(null, err => {});

catch 可以捕获它前面的错误,一般总是建议,Promise 对象后面要跟 catch 方法,这样可以处理 Promise 内部发生的错误

new Promise((resolve,reject) => {
  //错误回调会被catch捕获
  reject('reason');
}).then(data => {
  console.log('success',data);
}).catch(err => {
  console.log('err',err);
});

finally方法

Promise 状态发生变化时,不论如何变化都会执行,不变化不执行

finally() 本质上是 then() 的特例,会把响应的状态原样返回出去

new Promise((resolve, reject) => {
  // resolve(123);
  reject('reason');
})
.finally(() => {
   console.log('finally')
})
.catch(err => {
  console.log(err);
});

Promise.resolve

是成功状态 Promise 的一种简写形式

new Promise(resolve => resolve('foo'));
// 简写
Promise.resolve('foo');

传递参数:一般参数会一模一样被传递

Promise.resolve('foo').then(data => {
  console.log(data);
});

传递参数:Promise对象时,会直接返回这个Promise对象,什么都不做,后面的 then 会根据传递的 Promise 对象的状态变化决定执行哪一个回调

const p1 = new Promise(resolve => {
  setTimeout(resolve, 1000, '我执行了');
  // setTimeout(() => {
  //   resolve('我执行了');
  // }, 1000);
});
Promise.resolve(p1).then(data => {
  console.log(data);
});

// 等价于
p1.then(data => {
  console.log(data);
});
console.log(Promise.resolve(p1) === p1);

传递参数:具有 then 方法的对象,会执行then。特殊用法

const thenable = {
  then(resolve, reject) {
    console.log('then');
    resolve('data');
    // reject('reason');
  }
};
Promise.resolve(thenable).then(
  data => console.log(data),
  err => console.log(err)
);
console.log(Promise.resolve(thenable));

Promise.reject

失败状态 Promise 的一种简写形式

new Promise((resolve, reject) => {
  reject('reason');
});
// 等价于
Promise.reject('reason');

不管什么参数,都会原封不动地向后传递,作为后续方法的参数

Promise.all

Promise.all() 关注多个 Promise 对象的状态变化

传入多个 Promise 实例,包装成一个新的 Promise 实例返回

Promise.all() 的状态变化与所有传入的 Promise 实例对象状态有关,相当于(&&)操作
所有状态都变成 resolved,最终的状态才会变成 resolved
只要有一个变成 rejected,最终的状态就变成 rejected

Promise.race

Promise.race() 的状态取决于第一个完成的 Promise 实例对象,如果第一个完成的成功了,那最终的就成功;如果第一个完成的失败了,那最终的就失败。竞争实现结果

Promise.allSettled

Promise.allSettled() 的状态与传入的Promise 状态无关,永远都是成功的,它只会忠实的记录下各个 Promise 的表现

注意事项

resolve 或 reject 函数执行后的代码会正常执行
推荐在调用 resolve 或 reject 函数的时候加上 return,不再执行它们后面的代码

new Promise((resolve, reject) => {
  // return resolve(123);
  return reject('reason')     
});

Promise.all/race/allSettled 的参数问题:
参数如果不是 Promise 数组,会将不是 Promise 的数组元素转变成 Promise 对象
不只是数组,任何可遍历的都可以作为参数

Promise.all([1, 2, 3]).then(datas => {
  console.log(datas);
});
//等价于
Promise.all([
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.resolve(3)
]).then(datas => {
  console.log(datas);
});
上次编辑于: 2022/11/9 13:22:52
贡献者: lanjd