• 事件循环和任务队列


    如有错误欢迎指正,谢~

    我们都知道js是单线程语言,也就是只有一个线程,常称为主线程,在该线程中包含任务队列和执行栈

    任务队列:

    一些异步操作会将相关回调添加到任务队列中,而且不同的异步操作添加到队列的时间也不一样。

    eg:

    ①onclick 等异步是当事件触发立即会将回调放到任务队列中。

    ②settimeout 会等到延迟时间到了再把回调放到任务队列中。

    ③像网络请求ajax是等到请求完成的时候再把回调放到任务队列中去。

    执行栈:

    执行栈就相当于一个全局方法,主方法,里面有个同步任务和异步任务,主线程在执行碰到同步任务就执行,碰到异步任务就将其回调放到任务队列中,执行完同步任务之后,就开始执行任务队列了

    具体怎么划分看下面:

    macrotasks(就是我们平常说的任务队列)和microtasks的划分:

    macrotasks包括:script (整体代码),setTimeout,setInterval,setImmediate,

    microtasks包括:process.nextTick,Promises,Object.observe,MutationObserver

    宏观任务和微观任务可以这么理解:

    宏观任务1 队列          -------------------对应一个微观任务---------------   微观任务1队列

    宏观任务2 队列         -------------------对应一个微观任务---------------    微观任务2队列

            ...                                                                                                            ...

    宏观任务n 队列         -------------------对应一个微观任务---------------    微观任务n队列

    执行全部宏观任务队列1之后再去取微观全部1任务执行,任何执行完 ,第二轮宏观任务2队列执行全部执行完毕执行全部微观任务2,然后第3轮。。。。。循环下去

    那么我们来看一个例子:

    eg1:

     1 setTimeout(function(){
     2     console.log(1)
     3 },0);
     4 new Promise(function(resolve){
     5     console.log(2)
     6     for( var i=100000 ; i>0 ; i-- ){
     7         i==1 && resolve()
     8     }
     9     console.log(3)
    10 }).then(function(){
    11     console.log(4)
    12 });
    13 console.log(5);

    结果是

    2,3,5,4,1

    eg2:

     1 setTimeout(function(){
     2     console.log(1)
     3 },0);
     4 setTimeout(function(){
     5     console.log(6)
     6 },2000);
     7 new Promise(function(resolve){
     8     console.log(2)
     9     for( var i=100000 ; i>0 ; i-- ){
    10         i==1 && resolve()
    11     }
    12     console.log(3)
    13 }).then(function(){
    14     console.log(4);
    15     setTimeout(function(){
    16         console.log(8)
    17     },1000)
    18 });
    19 console.log(5);

    这个执行结果是啥呢???想想

    结果是:

    2,3,5,4,1,8,6

     eg3:

    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);

    node 环境下:

    3,4,6,8,5,1,2,7

    浏览器环境下:

    settimeout  优先级大于 setImmediate

    nextTick 优先级 大于 promise

    3,4,6,8,7,5,2,1

     eg4:

    //加入两个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

     1 async function async1(){
     2     console.log("async1 start");
     3     await async2();
     4     console.log("async1 end");
     5 }
     6 async function async2(){
     7     console.log("async2");
     8 }
     9 console.log("script start");
    10 setTimeout(function(){
    11     console.log("settimeout");
    12 },0);
    13 async1();
    14 new Promise(function(resolve){
    15      console.log("promise1");
    16      resolve()
    17 }).then(function(){
    18     console.log("promise2");
    19 })
    20 console.log("script end");

    //结果

    script start
    async1 start
    async2
    promise1
    script end
    promise2
    async1 end
    settimeout

    宏任务1队列:script start ,  async1 start , async2  ,promise1 , script end ----微任务队列1:promise2   (undefined) => { }(await Promise.resolve(undefined)的then(undefined){ (undefined) => { 这里才能拿到resolve的结果为undefined, 这是一个回调,异步操作,所以放到微任务中}})

    宏任务2队列:settimeout     -----微任务队列2  空空如也

    总结一下,便于自己学习,也分享大家一起学习。(#^.^#)

  • 相关阅读:
    [文字雲產生器] Tagxedo 把文字串成雲、變成畫,印在 T-Shirt、馬克杯、詩袋….
    python学习(六)
    根据URL地址获取域名
    python学习(五)
    Linux下查看Mysql数据库端口的方法
    python学习(四)
    python学习(三)
    python学习(二)
    Java String删除字符串中间的某部分
    Spring的一个入门例子
  • 原文地址:https://www.cnblogs.com/zhanghaiyu-Jade/p/11123762.html
Copyright © 2020-2023  润新知