zoukankan      html  css  js  c++  java
  • 事件循环的一些小啰嗦

    首先,在说这个之前,我们先把event loop再复习一遍:

    JS主线程不断的循环往复的从任务队列中读取任务,执行任务,其中运行机制称为事件循环(event loop).那么提到这里,在高层次上,JavaScript中有microtasks和macrotasks,它们是异步任务的一种类型.Microtasks的优先级要高于macrotasks,macrotasks用于处理I/O和计时器等事件.每次执行一个,microtask为async/await和Promise实现延迟执行,宁在每个task结束时执行.在每一个事件循环之前,microtask队列总是被执行完毕.

    我们在看看经常见到的一些微任务与宏任务的区别:

    1.微任务:process.nextTick,promise,MutationObserver

     2.宏任务:setTImeout,setTimeInterval,setImmediate,I/O,UI渲染

    注意哈:每个event loop都会有一个microtask queue,也会有一个或多个macrotask queue,一次任务可以放入macrotask queue,也可以放入microtask queue中.每一次event loop,会首先执行microtask queue,执行完成后,会提取macotask queue的一个任务加入macrotask queue,接着执行microtask queue,依次执行下去直至所有任务执行结束.

    我们再来看下异步执行机制吧.JS主线程拥有一个执行栈(同步任务)与一个任务队列,主线程回依次执行代码.当遇到同步任务时,会先将函数入栈,函数运行后再将该函数出栈;当遇到异步任务时,这些任务会返回一个值,让主线程不在此阻塞,使得主线程继续执行下去,而真正的任务交给了浏览器内核来执行,浏览器内核执行结束后,会将该任务事先定义好的回调函数加入相应的任务队列中.当JS主线程前空了执行栈后,会按先入先出的顺序读取microtasks queue的回调函数,并该函数入栈,继续运行执行栈,直到情况执行栈,再去读取任务队列.当微任务队列的任务执行完成后,会提取宏任务队列的一个任务加入微任务队列,接着继续执行微任务队列,依次执行下去直到所有任务全部执行结束.

    接下来,我们来依次看看几个比较常用的异步:

    1.setTimeout

    console.log('start1');
    setTimeout(function(){
    console.log('macro');
    },0)
    console.log('22')
    //输出顺序为:start1->22->macro

    2.Promise

    Promise本身是同步的立即执行函数,当在excutor中执行resolve或者reject的时候,此时是异步操作,会先执行then/catch等,当主栈完成后,才会去调用resolve/reject中存放的方法执行

    console.log('start')
    let promise1=new Promise(function(resolve){
    console.log('promise1')
    resolve()
    console.log('1end')
    }).then(function(){
    console.log('promise2')
    })
    setTimeout(function(){
    console.log('setTimeout')
    })
    console.log('send')
    //start->promise1->1end->send->promise2->setTimeout

    当JS主线程执行到Promise对象时,promise1.then()的回调就是一个task,promise1是resolved或rejected,那这个task就会放入当前事件循环回合的microtask queue中.如果是pending,这个task就会放入事件循环的某个回合的microtask queue中,我们再来看些例子吧:

    const p=Promise.resolve();//1.p的状态为resolve
    (async ()=>{
    await p;//2.返回,并将函数体后面的console放入下一个事件循环的microtask queue中
    console.log('await end');//5.执行,打印
    })();
    p.then(()=>{
    console.log('then 1');//3.p的状态变为resolve,会把p.then()放入当前事件循环的microtask queue中,因此打印then 1
    }.then(()=>{
    console.log("then 2");//4.打印then2
    })
    //输出:then 1->then 2->await end
    console.log('start');
    setTimeout(function(){
    console.log('setTimeout')
    },0)
    Promise.resolve().then(
    function(){
    console.log('promise1')
    }).then(function(){
    console.log('promise2')
    });
    console.log('end');
    //输出结果:start->end->promise1->promise2->setTimeout

    3.async await

    async function async1(){
    console.log('async1 start');
    await async2();
    console.log('async2 end')
    }
    async function async2(){
    console.log('async2')
    }
    console.log('script start')
    async1();
    console.log('script end')
    //script start->async1 start->async2->scirpt end ->async2 end

    async函数返回一个Promise对象,当函数执行的时候,一旦遇到await就会先返回,等到出发的异步操作完成,再执行函数体被那个后面的语句,可以理解为是让出了线程,跳出了async函数体.

  • 相关阅读:
    软件开发术语定义
    软件开发流程纲要及各个阶段产生的文档
    Java封装自己的Api
    Java中如何使封装自己的类,建立并使用自己的类库?
    Struts2中ActionContext和ServletActionContext
    TP-Link 无线路由器设置图文教程----怎么设置TP-Link无线路由器图解
    数据库(第一范式,第二范式,第三范式)
    ORACLE配置tnsnames.ora文件实例
    Windows下64位Apache服务器的安装
    公司内部Oracle RAC测试环境的简单使用说明.
  • 原文地址:https://www.cnblogs.com/ljylearnsmore/p/14537145.html
Copyright © 2011-2022 走看看