Promise系列reject后catch/then的有关问题

4,056 阅读4分钟

前言

记录11.26遇到的Promise相关的问题,回想当时明明是知道的,因为才睡醒没准备好真的是回答的太差了,狠狠复习一下Promise.

正文

问题

  1. Promise.all()怎么运作的?
  2. Promis.reject(1).then(console.log).catch(console.log).then(console.log).catch(console.log)运行到哪里

回顾Promise(MDN)

1. Promise是什么

Promise用于表示一个异步操作的最终完成或失败及其结果值。使异步操作可以像同步方法那样返回值:异步方法返回一个promise 一个promise有三个状态——pending\rejected\fulfilled

image.png

2. 链式调用(then)

连续执行两个或多个异步操作,在上一个操作执行成功之后,开始下一个操作,并带着上一步操作所返回的结果。then()函数返回一个新的Promise 当一个Promise 完成失败时,返回函数异步调用

  • 返回了一个值,那么 then 返回的 Promise 将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
  • 没有返回任何值,那么 then 返回的 Promise 将会成为接受状态,并且该接受状态的回调函数的参数值为 undefined
  • 抛出一个错误,那么 then 返回的 Promise 将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。

3. 一些静态方法

  • Promise.all()
    该方法返回一个新的promise对象,该对象中所有的promise对象都成功才触发成功,如果有一个对象失败则立即触发该对象的失败,这个新的promise对象触发成功后,返回包含其中所有promise返回值的数组,顺序和传入的一致;如果触发失败状态,返回第一个触发失败的promise对象的错误信息。
  • Promise.race()
    当传入的任何一个子promise被成功或失败后,父promise马上调用子promise的成功或失败详情作为参数调用父promise,并返回该promise对象。
  • Promise.reject(reson)
    返回一个状态为失败的Promise对象,并传递给对应的处理方法。
  • Promise.resolve(value)
    返回一个状态由给定value决定的Promise对象,如果是带有then方法的对象,返回的对象由then方法执行决定;如果value为空,返回的Promise对象状态为fulifilled,并且传递该value给对应的then方法。

回答问题!!

1. Promise.all(iterable)怎么运作的?

Promise.all()方法传入一个promise 的iterable类型(Array、Map、Set),返回一个Promise实例。 这个Promise的resolve回调是在输入的所有promise的resolve回调都结束;只要任何一个输入的promise的reject回调执行,立即抛出错误。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
      setTimeout(resolve, 100, 'foo');
    });

Promise.all([promise1, promise2, promise3]).then((values) => {
       console.log(values);
    });
//  output: Array [3, 42, "foo"]

2.Promise.reject(1).then(console.log).catch(console.log).then(console.log).catch(console.log)

首先明白catch()是什么!
catch方法返回一个Promise,并且处理拒绝的情况,它的行为和then是相同的

然后分析题目:

  1. 首先看结果
let p = Promise.reject(1).then(console.log('then1')).catch(console.log('catch1')).then(console.log('then2')).catch(console.log('catch2'))
console.log(p)
setTimeout(() => {
    console.log(p);
})

//输出
then1
catch1
then2
catch2
Promise { <pending> }
(node:54428) UnhandledPromiseRejectionWarning: 1
Promise { <rejected> 1 }

如果调用 then 的 Promise 的状态(fulfillment 或 rejection)发生改变,但是 then 中并没有关于这种状态的回调函数,那么 then 将创建一个没有经过回调函数处理的新 Promise 对象,这个新 Promise 只是简单地接受调用这个 then 的原 Promise 的终态作为它的终态。

  1. 开始一顿分析

    1. reject(1)方法,返回一个状态为失败的Promise对象

    2. .then(console.log('then1')), 返回的失败状态的Promise调用then()方法,但是其中没有这种状态的回调函数,所以创建并返回一个和原始Promise失败状态相同的Promise对象

    3. catch(console.log('catch1')),根据前边分析,是一个失败状态的Promise调用catch方法,但是其中没有这种状态的回调函数,所以返回一个失败状态的Promise,输出catch1

    4. then(console.log('then2')).catch(console.log('catch2')),这些后边的同理。

  2. 分析重点

    1. catchthen本质上区别不大,最后都会返回一个新的Promise对象
    2. 另外注意Promise状态变成fulfilled或者rejected后不可以改变状态

总结

reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch

之前只知道Promise状态变成fulfilled或者rejected以后不可以改变状态,没有注意then、catch返回的东西和then()方法中如果没有处理状态的回调函数应该返回什么。

总之,仔仔细细多看文档,不要只了解表面!!