美文网首页
关于promise的执行顺序问题

关于promise的执行顺序问题

作者: Eileen_1d88 | 来源:发表于2021-03-16 18:58 被阅读0次

    看到这样一段代码

    Promise.resolve().then(() => {
      console.log(0);
      return Promise.resolve(4) // p2
    }).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);
    })
    result: 0123456
    

    对此结果非常疑惑,百思不得其解,本来觉得结果应该是0142356

    最后经过多方搜索,在知乎山看到这样一个问题关于promise输出顺序的疑问?, 紫云飞大大的回答解决了我的疑惑,但是大大的解答太过抽象,我也是自己摸索好久才万全明白,在此记录一下。

    问题的关键在于在promise内部返回一个thenable对象会发生什么?
    1、promise的then是一个microtask微任务
    2、promise p return一个promise p2的时候,其实是将这个p2的then加入到了微任务队列中,同时将p的resolve和reject传给p2
    3、p2中的then全部调用完成之后,会将p的resolve放入微任务队列,resolve完成之后,这个时候p的状态才会变化,继续执行p的then

    所以以上代码的执行过程就是:

    输出 微任务队列
    [0, 1]
    0 [1, p2-then]
    1 [p2-then, 2]
    [2, resolve]
    2 [resolve, 3]
    [3, 4]
    3 [4, 5]
    4 [5, 6]
    5 [6]
    6 []

    一下是几个例子,加深一下理解(队列中的元素对应的是元素所在的then)

    Example1
    new Promise((resolve, reject) => {
      console.log("外部promise");
      resolve();
    })
      .then(() => {
        console.log("外部第一个then");
        return new Promise((resolve, reject) => {
          console.log("内部promise");
          resolve();
        })
        .then(() => {
        console.log("内部第一个then");
        })
        .then(() => {
        console.log("内部第二个then");
        });
      })
      .then(() => {
        console.log("外部第二个then");
      });
    
    输出 微任务队列
    外部promise [外部第一个then]
    外部第一个then []
    内部promise [内部第一个then]
    内部第一个then [内部第二个then]
    内部第二个then [resolve]
    [外部第二个then]
    外部第二个then []
    Example2
    new Promise((resolve, reject) => {
      console.log("外部promise");
      resolve();
    })
      .then(() => {
        console.log("外部第一个then");
        new Promise((resolve, reject) => {
          console.log("内部promise");
          resolve();
        })
          .then(() => {
            console.log("内部第一个then");
          })
          .then(() => {
            console.log("内部第二个then");
          });
      })
      .then(() => {
        console.log("外部第二个then");
      });
    
    输出 微任务队列
    外部promise [外部第一个then]
    外部第一个then []
    内部promise [内部第一个then]
    [内部第一个then, 外部第二个then]
    内部第一个then [外部第二个then, 内部第二个then]
    外部第二个then [内部第二个then]
    内部第二个then []
    Example3
    new Promise((resolve, reject) => {
      console.log("外部promise");
      resolve();
    })
      .then(() => {
        console.log("外部第一个then");
        let p = new Promise((resolve, reject) => {
          console.log("内部promise");
          resolve();
        })
        p.then(() => {
            console.log("内部第一个then");
          })
        p.then(() => {
            console.log("内部第二个then");
          });
      })
      .then(() => {
        console.log("外部第二个then");
      });
    
    输出 微任务队列
    外部promise [外部第一个then]
    外部第一个then []
    内部promise [内部第一个then]
    [内部第一个then,内部第二个then]
    [内部第一个then, 内部第二个then, 外部第二个then]
    内部第一个then [内部第二个then, 外部第二个then]
    内部第二个then [外部第二个then]
    外部第二个then []
    Example4
    let p = new Promise((resolve, reject) => {
      console.log("外部promise");
      resolve();
    })
    p.then(() => {
        console.log("外部第一个then");
        new Promise((resolve, reject) => {
          console.log("内部promise");
          resolve();
        })
          .then(() => {
            console.log("内部第一个then");
          })
          .then(() => {
            console.log("内部第二个then");
          });
      })
    p.then(() => {
        console.log("外部第二个then");
      });
    
    输出 微任务队列
    外部promise [外部第一个then, 外部第二个then]
    外部第一个then 内部promise [外部第二个then, 内部第一个then]
    外部第二个then [内部第一个then, 内部第二个then]
    内部第一个then [内部第二个then]
    内部第二个then []
    Example5
    new Promise((resolve, reject) => { // p
      console.log('外部promise');
      resolve();
    })
      .then(() => {
        console.log('外部第一个then');
        new Promise((resolve, reject) => { // p2
          console.log('内部promise');
          resolve();
        })
          .then(() => {
            console.log('内部第一个then');
            return Promise.resolve(); // p3
          })
          .then(() => {
            console.log('内部第二个then');
          })
      })
      .then(() => {
        console.log('外部第二个then');
      })
      .then(() => {
        console.log('外部第三个then');
      })
    
    输出 微任务队列
    外部promise [外部第一个then]
    外部第一个then 内部promise [内部第一个then]
    [内部第一个then, 外部第二个then]
    内部第一个then [ 外部第二个then, p3-then]
    外部第二个then [p3-then, 外部第三个then]
    [外部第三个then, p2-resolve]
    外部第三个then [p2-resolve]
    [内部第二个then]
    内部第二个then []
    Example6
    new Promise((resolve, reject) => { // p
      console.log("外部promise");
      resolve();
    })
      .then(() => {
        console.log("外部第一个then");
        new Promise((resolve, reject) => { // p2
          console.log("内部promise");
          resolve();
        })
          .then(() => {
            console.log("内部第一个then");
          })
          .then(() => {
            console.log("内部第二个then");
          });
        return new Promise((resolve, reject) => { // p3
          console.log("内部promise2");
          resolve();
        })
          .then(() => {
            console.log("内部第一个then2");
          })
          .then(() => {
            console.log("内部第二个then2");
          });
      })
      .then(() => {
        console.log("外部第二个then");
      });
    
    输出 微任务队列
    外部promise [外部第一个then]
    外部第一个then 内部promise [内部第一个then]
    内部promise2 [内部第一个then, 内部第一个then2]
    内部第一个then [内部第一个then2, 内部第二个then]
    内部第一个then2 [内部第二个then, 内部第二个then2]
    内部第二个then [内部第二个then2]
    内部第二个then2 [p-resolve]
    [外部第二个then]
    外部第二个then []
    Example7
    new Promise((resolve, reject) => { // p
      console.log("外部promise");
      resolve();
    })
    .then(() => {
        console.log("外部第一个then");
        new Promise((resolve, reject) => { // p2
            console.log("内部promise");
            resolve();
        })
        .then(() => {
            console.log("内部第一个then");
        })
        .then(() => {
            console.log("内部第二个then");
        });
        return new Promise((resolve, reject) => { // p3
            console.log("内部promise2");
            resolve();
        })
        .then(() => {
            console.log("内部第一个then2");
        })
        .then(() => {
            console.log("内部第二个then2");
        });
    })
    .then(() => {
        console.log("外部第二个then");
    });
    
    输出 微任务队列
    外部promise [外部第一个then]
    外部第一个then 内部promise [内部第一个then]
    内部promise2 [内部第一个then, 内部第一个then2]
    内部第一个then [内部第一个then2, 内部第二个then]
    内部第一个then2 [内部第二个then, 内部第二个then2]
    内部第二个then [内部第二个then2]
    内部第二个then2 [p-resolve]
    [外部第二个then]
    外部第二个then []

    2021年8月31日
    最近手动写了一遍Promise,可能有点晚。但是明白了为什么promise返回一个promise的时候会需要等一下才能显示,因为Promise的resolvePromise(x, promise, resolve, reject)方法,如果x是一个promise,那么会调用一次then.call(x, y => {resolvePromise(y, promise, resolve, reject)}, reject), then是微服务,所以需要再次进入微服务队列排队,所以会有这样的现象

    相关文章

      网友评论

          本文标题:关于promise的执行顺序问题

          本文链接:https://www.haomeiwen.com/subject/nkudcltx.html