Promise链及静态方法


多个期约组合在一起可以构成强大的代码逻辑。这种组合可以通
过两种方式实现:期约连锁与期约合成

一、Promise链

每个Promise方法都会返回一个新的Promise对象,新Promise又有自己的方法,这样就可以实现Promise链

let p = new Promise((resolve, reject) => {
    
    
    console.log('first');
    resolve();
});
 p.then(() => console.log('second'))
  .then(() => console.log('third'))
  .then(() => console.log('fourth'));
// first
// second
// third
// fourth

实现了一串同步任务,但这并不是异步链,要真正执行异步任务,可以让每个执行器都返回一个期约实例,这样就可以让其他的处理程序(handler)将等待它 settled 后再获得其结果(result)

例:

    let p = new Promise((resolve, reject) => {
    
    
        console.log('1');
        setTimeout(resolve, 1000);
    });
    p.then(() => new Promise((resolve, reject) => {
    
    
        console.log('2');
        setTimeout(resolve, 1000);
    }))
    .then(() => new Promise((resolve, reject) => {
    
    
        console.log('3');
        setTimeout(resolve, 1000);
    }));

    //1 (1秒后)
    //2 (2秒后)
    //3 (3秒后)

Promise链正好解决了回调地狱问题,且then()、catch()、finally()都返回Promise,可以同时串行

二、Promise合成

1. Promise.all()

这个静态方法接收一个可迭代对象(通常为数组),返回一个新期约

  1. 当所有给定的 promise 都被 settled 时,新的 promise 才会 resolve,并且其结果数组将成为新的 promise 的结果
let p = Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]);
console.log(p); // Promise <pending>

p.then(()=>{
    
    console.log(p)}); // Promise <fulfilled> <value>:[1,2,3] 当上面这些 promise 准备好时:每个 promise 都贡献了数组中的一个元素

请注意,结果数组中元素的顺序与其在源 promise 中的顺序相同。即使第一个 promise 花费了最长的时间才 resolve,但它仍是结果数组中的第一个。(按迭代器顺序)

  1. 如果至少有一个包含的期约待定,则合成的期约也会待定。
let p1 = Promise.all([new Promise(() =>
{
    
    })]);// 永远pending

let p2 = Promise.all([
Promise.resolve(),
Promise.reject(),
Promise.resolve()
]);
  1. 如果任意一个 promise 被 reject,由 Promise.all 返回的 promise 就会立即 reject,并且带有的就是这个 error

let p =Promise.all([
  new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
  new Promise((resolve, reject) => setTimeout(() => (console.log('test');reject(3)), 3000))
]).catch(alert); // Error: Whoops!

//test

第二个Promise被reject,拒绝的理由作为Promise.all拒绝的理由(Error:3)
之后再拒绝的Promise不会影响最终Promise.all的理由,但是会正常运行(输出test,静默处理reject(3) 不会有未处理的错误)

2. Promise.allSettled

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

Promise.all([
  fetch('/template.html'),
  fetch('/style.css'),
  fetch('/data.json')
]).then(render); // render 方法需要所有 fetch 的数据

ps.该语言是ES2020新的内容,旧浏览器需要使用polyfill

3. Promise.race()

与 Promise.all 类似,但只等待第一个 settled 的 promise 并获取其结果(或 error)

// 解决先发生,超时后的拒绝被忽略
let p1 = Promise.race([
Promise.resolve(3),
new Promise((resolve, reject) =>
setTimeout(reject, 1000))
]);
setTimeout(console.log, 0, p1); // Promise <resolved>: 3

与Promise.all()类似,第一个settled之后的Promise还会正常执行,也会静默处理所有reject操作

三、Promise.resolve/reject

除了执行器函数进行settled还可以用以下两个静态方法进行settled:(用的不多)

1. Promise.resolve()

Promise.resolve(value) 用结果 value 创建一个 resolved 的 promise。
以下两个相等

let p1 = new Promise((resolve, reject) =>
resolve());
let p2 = Promise.resolve();

2. Promise.reject()

Promise.reject(error) 用 error 创建一个 rejected 的 promise。

四、Promise静态方法总结

Promise 类有 5 种静态方法:

  1. Promise.all(promises) —— 等待所有 promise 都 resolve 时,返回存放它们结果的数组。如果给定的任意一个 promise 为 reject,那么它就会变成 Promise.all 的 error,所有其他 promise 的结果都会被忽略。
  2. Promise.allSettled(promises)(ES2020 新增方法)—— 等待所有 promise 都 settle 时,并以包含以下内容的对象数组的形式返回它们的结果:
    • status: “fulfilled” 或 “rejected”
    • value(如果 fulfilled)或 reason(如果 rejected)。
  3. Promise.race(promises) —— 等待第一个 settle 的 promise,并将其 result/error 作为结果。
  4. Promise.resolve(value) —— 使用给定 value 创建一个 resolved 的 promise。
  5. Promise.reject(error) —— 使用给定 error 创建一个 rejected 的 promise。

猜你喜欢

转载自blog.csdn.net/S_aitama/article/details/110825773