Promise引见--异步篇

这部分内容源于知乎上的一个发问

setTimeout(function(){console.log(4)},0);
new Promise(function(resolve){
    console.log(1)
    for( var i=0 ; i<10000 ; i++ ){
        i==9999 && resolve()
    }
    console.log(2)
}).then(function(){
    console.log(5)
});
console.log(3);

// 1
// 2
// 3
// 5
// 4

之前我们说过then要领增加的回调函数都是异步实行的,所以根据我们一般的认知,效果应该是12345,由于4是先增加到异步行列,而5在今后增加到异步行列。

知乎的题目也有何幻大神细致的解说。这里我就简朴的说一下吧。

我们都晓得javascript是单线程的,也就是说,一个时间只能做一件事。所以,一切的使命都要根据肯定的递次列队,然后一个一个实行。假如一切的使命都是同步的,那就没有什么题目,代码根据夙昔到后的递次顺次实行就能够了,但我们现实工作历程当中,不免会有一些操纵须要异步实行——比方事宜,比方ajax,比方setTimeout

所以,浏览器会保护一个使命行列(task queue),使命行列是先进先出的,也就是说,先进入使命行列的会先实行。当主线程使命实行终了,就会检察使命行列中有没有新使命,假如有,则把第一个使命放到主线程中实行,以此轮回往复,这个历程也就是Event loops

我之前也一直都认为浏览器中只要一个使命行列,看到这个题目后才晓得。本来浏览器中的使命行列不止一个,且优先级也差别。基本上能够分为以下两种:

macro-task: script(团体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
micro-task: process.nextTick, 原生Promise, Object.observe, MutationObserver

我们看到原生PromisesetTimeout离别属于micro-taskmacro-task。我们之前说的异步使命行列,指的是macro-task。而micro-task的实行递次,与之差别。

在实行完主线程上的一切使命时,会先去检察micro-task行列中有没有使命,假如有,则顺次实行micro-task行列中的一切使命,今后才去检察macro-task行列。每次拿到macro-task行列上使命并实行今后,都会去搜检micro-task行列,以此轮回。所以上面题目中效果是12354就很明了了。

我们看一个例子,并细致诠释它的实行流程。

console.log('script1');

setTimeout(function() {
  console.log('setTimeout1');
}, 300);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script2');

setTimeout(function() {
  console.log('setTimeout2');
  Promise.resolve().then(function() {
    console.log('promise3');
  })
}, 0);

// script1
// script2
// promise1
// promise2
// setTimeout2
// promise3
// setTimeout1

效果如代码中解释所示。详细实行步骤以下:

①代码从上到下实行,先打印出script1

②实行到第一个setTimeout时,发明300ms后把函数增加到macro-task行列中。

③实行Promise时,顺次把输出promise1promise2的使命增加到micro-task行列。

④打印script2

⑤实行第二个setTimeout时由于设置的是0ms,所以马上(实在浏览器有起码4ms的限定)增加到macro-task行列中。

⑥主线程实行终了则搜检micro-task行列并实行,输出promise1promise2

⑦然后搜检macro-task行列,输出setTimeout2,并把输出promise3的使命增加到micro-task行列。

⑧再次搜检micro-task行列并实行,输出promise3

⑨末了搜检macro-task行列,输出setTimeout1,由于它是300ms后增加到macro-task行列,所今后输出。

范例中的流程是这个模样,然则差别的浏览器中,现实输出的效果可能会不相同。以上是最新版本的chrome中测试效果。

末了,引荐一篇外国朋友的博客,我就是看了这篇文章才完整弄清楚的,内里内容讲的迥殊细致。

    原文作者:武官尚书
    原文地址: https://segmentfault.com/a/1190000007936922
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞