Promise炖锅之API篇

235 阅读4分钟

前言

阅读本文前请先了解宏任务与微任务、EventLoop机制\color{#33CC99}{宏任务与微任务、EventLoop机制}宏任务与微任务、EventLoop机制等基本概念

20210412-122212(WeLinkPC).png

API

Promise.prototype.then()

返回的是一个promise,可以链式调用

  • then方法中返回值或者没返回值时,返回promise为resolved状态
new Promise((resolve, reject) => {
  resolve(1);
}).then(data => {
    console.log(data);
    return 2;
}).then(data => {
    console.log(data)
}).then(data => {
    console.log(data)
})
// 输出 1 2 undefined
  • 返回一个rejected或resolved的promise,返回promise为前者状态
new Promise((resolve, reject) => {
  resolve(1);
}).then(data => {
    console.log(data);
    return Promise.resolve(2);
}).catch(err => { 
    console.log(err)
}).then(data => {
    console.log(data)
    throw("3")
}).catch(err => {
    console.log(err)
})
// 输出1 2 3
  • 在then方法中,若只是执行resolve()或者reject(),并没有返回的话,后续的then/catch执行函数入参为undefined
new Promise((resolve, reject) => {
  resolve(1);
}).then(data => {
    console.log(1);
    Promise.resolve(2);
}).catch(err => { console.log(err)
}).then(data => {
   console.log(data)
   throw("3")
}).catch(err => {
    console.log(err)
})
// 输出1 undefined 3
// Promise.resolve(2)这里并未return
  • then()里执行异步任务
new Promise((resolve, reject) => {
    resolve(1)
}).then(data => {
    setTimeout(() => {
      console.log(data)
      Promise.resolve(2);
    }, 1000);
}).then(data => {
   console.log(data);
})
// 输出 undefined 1
// setTimeout为宏观任务,且第一个then并未返回promise
  • then()里执行异步任务,但希望后续的then()同步执行
new Promise((resolve, reject) => {
    resolve(1)
}).then(data => {
    return new Promise((resolve,reject) => {
      setTimeout(() => {
        console.log(data)
        resolve(2);
      }, 500)
    })
}).then(data => {
   console.log(data);
})
// 输出 1 2

Promise.prototype.catch()

catch方法返回一个Promise,若catch方法抛出错误或返回一个rejected的Promise,该返回Promise状态为rejected;否则,该返回Promise状态为resolved

  • 在异步函数中抛出的错误不会被catch捕获到;但reject会被捕获到
new Promise((resolve, reject) => {
  setTimeout(() => {
    throw "p Error";
  }, 1000);
}).catch((e) => {
  console.log(e);
});
// 抛出异常 Uncaught p Error
new Promise((resolve, reject) => {
  setTimeout(function() {
    reject("p Error");
  }, 1000);
}).catch((e) => {
  console.log(e);
});
// 输出 p Error
  • 在resolve()后面抛出的错误会被忽略
new Promise((resolve, reject) => {
  resolve();
  throw "p1 Error";
}).catch((e) => {
  console.log(e);
});
// 无输出
  • catch捕获后,若catch方法抛出错误或返回Promise.reject(),该返回Promise状态为rejected
new Promise((resolve, reject) => {
  reject(1);
}).catch(e => {
  console.log(e);
  return Promise.reject(2);
}).then(() => {
    console.log(3);
}).catch(e => {
    console.log(e)
})
// 输出 1 2
// 第一个catch捕获到异常,输出1,然后返回了rejected的promise
// 第二个catch捕获到上述的promise,输出2
复制代码
new Promise((resolve, reject) => {
  reject(1);
}).catch(e => {
  console.log(e);
  Promise.reject(2);
}).then(() => {
    console.log(3);
}).catch(e => {
    console.log(e)
})
// UnhandledPromiseRejectionWarning
// 因为第一个catch未返回失败的promise,而是直接执行了,导致第二个catch捕获失败,抛出异常

Promise.prototype.finally()

返回一个promise,注意执行时机是在前面的promise状态确定后,其他特性与then、catch一致

Promise.all(iterable)

当iterable均resolved后,Promise.all状态变为resolved;若其中有一个rejected,Promise.all状态立刻变为rejected

  • iterable可以为空数组或空字符串,此时相当于Promise已经resolved;若为空,会抛出Promise异常
Promise.all([]).then(res=>{
    console.log(res)
})
// 输出[]
Promise.all("").then(res=>{
    console.log(res)
})
// 输出[]
Promise.all().then(res=>{
    console.log(res)
})
// Promise报错
// Uncaught (in promise) TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
    at Function.all (<anonymous>)
    at <anonymous>:1:

  • iterable若非Promise,相当于Promise已经resolved
let promise1 = new Promise((resolve,reject)=>{
    resolve(1)
})
let promise2 = new Promise((resolve,reject)=>{
    resolve(2)
})
Promise.all([promise1,promise2,3]).then(res=>{
    console.log(res)
})
// 输出[1,2,3]

Promise.race(iterable)

Promise.race状态与iterable中第一个返回的状态相同

let promise = new Promise((resolve,reject)=>{
    reject(1)
})

Promise.race([promise,2]).then(res=>{
    console.log(res)
}).catch(err => {console.log(err)})
// 输出1
  • 注意与下例的区别,顺序不同导致输出不同,体会一下
let promise = new Promise((resolve,reject)=>{
    reject(1)
})

Promise.race([2,promise]).then(res=>{
    console.log(res)
}).catch(err => {console.log(err)})
// 输出2
  • 当使用定时器,resolve()变成了宏任务,输出又不同了
let promise = new Promise((resolve,reject)=>{
    setTimeout(function() {resolve(1)}, 1000);
})

Promise.race([promise,2]).then(res=>{
    console.log(res)
})
// 输出2

所以,要深刻体会 第一个 的意思

  • iterable为空数组或空字符串,会一直等待,这点与Promise.all不一样;若为空,会抛出Promise异常
Promise.race([]).then(res=>{
    console.log(res)
}).catch(e => {console.log(e)})
// 什么都不输出

Promise.allSettled(iterable)

当iterable数组均执行完成(resolve或reject),Promise.all状态变为resolved,其入参是iterable的每个promise结果,包含status字段表明该iterable的执行结果

  • iterable均执行结束后,allSettled状态变为resolve
const promise1 = Promise.resolve(3);
const promise2 = Promise.reject(2);

Promise.allSettled([promise1, promise2])
  .then((results) => results.forEach((result) => console.log(result.status)));
// 输出 
// fulfilled
// rejected
  • iterable若非Promise,相当于Promise已经resolved
  • iterable为空数组或空字符串,会一直等待,这点与Promise.all不一样;若为空,会抛出Promise异常

Promise.any(iterable)

iterable中第一个resolved后,Promise.any变为resolved;若iterable数组都rejected了,Promise.any变为rejected 该API尚未被所有浏览器支持!!!处于Stage4状态!!!不建议使用!!!

  • 和race不一样,race等待第一个完成的promise,any等待第一个成功的promise;其他与race一致