Promise的then的链式调用

458 阅读2分钟
  1. 先看Promise关于then的一段代码输出:

    Promise.resolve().then(()=>{
        console.log(0);
        return Promise.resolve(4);
    }).then((res)=>{
        console.log(res)
    })
    Promise.resolve().then(()=>{
        console.log(1);
    }).then(()=>{
        console.log(2);
    }).then(()=>{
        console.log(3);
    }).then(()=>{
        console.log(5);
    }).then(()=>{
        console.log(6);
    })
    
    输出:
    0
    1
    2
    3
    4 // 发现4被推迟了两个时序,多个promise之间的then是交替运行的
    5
    6
    
    /*
            输出0 ->
    
            首先,浏览器会创建一个 PromiseResolveThenableJob 去处理这个 Promise(resolved) 实例(then后面的函数是返回一个promise的,在函数体里面不可以再返回无状态的promise,否则会陷入无限循环),这是一个微任务。
    
            进入另一个then,输出1 ->
    
            接着,等到下次循环运行到这个微任务时,也就是PromiseResolveThenableJob 执行中的时候,因为这个Promise 实例是fulfilled(resolved)状态,所以又会注册一个它的.then()回调。
    
            进入另一个then,输出2 ->
    
            等到下一次循环到这个Promise 实例,它的.then()回调执行后,才会将参数传给下一个then(输出res,等到下一次循环时,该参数会被输出),于是就被推迟了两个时序
    
            进入另一个then,输出3 ->
    
            接收到参数,输出4 ->
    
            输出5 ->
    
            输出6
    */
    
  2. V8引擎关于promise的源码:

    image-20210507010551213

    return Promise.resolve(4)时,相当于 return new Promise(resolve=>resolve(4)),这个时候执行return时,会去判断返回的是不是一个promiseIsPromise),是的话,执行x.then,这时候相当于递归调用,递归调用的代码会在下一次事件循环执行(此时已经输出了0,1,接着输出2);之后代码运行到这次递归,执行resolve(4),此时输出3,等到再下一次运行到此处代码时,输出4。

  3. resolve的本质:resolve()是用来表示promise的状态为fullfilled,相当于只是定义了一个有状态的Promise,但是并没有调用它;

    使用then时需注意:

    • promise调用then的前提是该promise的状态为fullfilled
    • 只有promise调用then的时候,then里面的函数才会被推入微任务中;
  4. 单个promise的链式调用:

    1. 当promise执行时,会创建一个pending状态的promise对象,执行promise函数体中的代码;

      • 若函数体的状态为fullfilled时,才会调用then的代码,并将then的代码放入此次事件循环微任务队列中;
      • 若函数体的状态为pending时,then后面的代码会被放入该promise中的队列中,等到该promise的状态变为fullfilled时,才将这些代码推入此次事件循环微任务队列中立即执行。

      示例:

      new Promise((resolve, reject) => {
              console.log("promise")
              resolve()
      })
      .then(() => {	// 执行.then的时候生成一个promise是给最后一个.then的
              console.log("then1")
          new Promise((resolve, reject) => {
              console.log("then1promise")
              resolve()
              })
              .then(() => {// 执行这个.then的时候,生成的promise是下面一个then的
              console.log("then1then1")
          })
          .then(() => {
              console.log("then1then2")
              })
      })
      .then(() => {
        // 这个
              console.log("then2")
      })
      
      输出:
      promise
      then1
      then1promise
      then1then1
      then2
      then1then2