node中的setTimeout,setInterval,promise.then和process.nextTick()的执行顺序

1.javascript事件循环:

同步任务:直接通过主线程执行,如script代码
异步任务:进入Event Table,并注册回调函数——> Event Queue,等主线程的执行栈为空时候,读取Event Queue里面的函数就,进入主线程。如setTimeout,promise.then()等;
那怎么知道主线程的执行栈为空呢,JS引擎存在monitoring process进程,它会持续检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。

    let data = [];
   $.ajax({
       url:www.javascript.com,
       data:data,
       success:() => {
           console.log('发送成功!');
       }
   })
  console.log('代码执行结束');

ajax进入Event Table,注册回调函数success。
执行console.log(‘代码执行结束’)。
ajax事件完成,回调函数success进入Event Queue。
主线程从Event Queue读取回调函数success并执行。

2.setTimeout和setInterval

setTimeout(() => { a() },3000)

b(10000000)//b代表一个执行需要耗时很久的函数

a进入Event Table,注册回调函数success。
执行b函数,但是b函数执行时间超出了3秒钟
3秒钟到了,success进入Event Queue,但是以为主线程没有执行完,只能等。
b函数执行完了,主线程从Event Queue读取回调函数success并执行。

有时候我们这样写:setTimeout(()=>{},0),即使主线程执行栈是空的,这个并不是立即0毫秒执行,setTimeout有最小时间间隔限制,HTML5标准为4ms,小于4ms按照4ms处理,但是每个浏览器实现的最小间隔都不同.setInterval最小时间间隔为10ms;

4.promise与process.nextTick();

宏任务:上面我们说到的script代码,setTimeoutsetInterval

微任务:promise.then(),process.nextTick();且preocess.nextTick优先级大于promise.then;

console.log('1');
 
setTimeout(function() {
    console.log('2');
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
 
    process.nextTick(function() {
        console.log('3');
     })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})
 
setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})

宏任务:1、7 (这两个是同步任务,所以先执行)

微任务:6、8 (微任务,process.nextTick():6优先于promise.then(): 8)

宏任务:2、4 (第一个setTimeout)

微任务:3、5 (微任务,process.nextTick():3优先于promise.then() :5)

宏任务:9、11 (第二个setTimeout)

微任务:10、12 (微任务,process.nextTick():10优先于promise.then() :12)

输出:

1
7
6
8
2
4
3
5
9
11
10
12

总结:

1.先是宏任务–>微任务–>宏任务–>微任务一直循环下去;

2.script代码为第一层宏任务,如果有setTimeout,setInterval,则他们的回调函数会成为第二层,第三层…第n层的的宏任务,一个setTimeout是一个宏任务(重点),而不是几个setTimeout合在一起为一个宏任务,所以9会在3,5之后

3.promise.then()和process.nextTick()是微任务,在执行完该一层的宏任务后执行,且process.nextTick()优先于promise.then();

4.同步代码执行顺序优先级高于异步代码执行顺序优先级;

5.new Promise(fn)中的fn是同步执行;

练习

延迟 0 毫秒的 setTimeout() 回调setImmediate()非常相似。 执行顺序取决于各种因素,但是它们都会在事件循环的下一个迭代中运行。
而传给process.nextTick()的函数会在事件循环的当前迭代中(当前操作结束之后)被执行。 这意味着它会始终在 setTimeout 和 setImmediate 之前执行。

例子一:
setImmediate(function(){
  console.log(1);
},0);
setTimeout(function(){
  console.log(2);
},0);
new Promise(function(resolve){
  console.log(3);
  resolve();
  console.log(4);
}).then(function(){
  console.log(5);
});
console.log(6);
process.nextTick(function(){
  console.log(7);
});
console.log(8);

输出:

3
4
6
8
7
5
1
2

例子二:
//加入两个nextTick的回调函数
process.nextTick(function () {
  console.log('nextTick延迟执行1');
});
process.nextTick(function () { 
  console.log('nextTick延迟执行2');
});
// 加入两个setImmediate()的回调函数
setImmediate(function () {
  console.log('setImmediate延迟执行1'); 
  // 进入下次循环 
  process.nextTick(function () {
    console.log('强势插入');
  });
});
setImmediate(function () {
  console.log('setImmediate延迟执行2'); 
});

console.log('正常执行');

输出:

正常执行
nextTick延迟执行1
nextTick延迟执行2
setImmediate延迟执行1
强势插入
setImmediate延迟执行2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值