本文涵盖了面试题的介绍和一些关于事件循环面试题执行顺序的问题通过微任务、事件循环、定时器的面试题,etc.深入理解结论面试题总结面试题如下。大家可以先试着写输出结果,再看我下面的详细解释,看看有没有出入。如果你理解了整个顺序和Node.js的执行顺序应该就没问题了。asyncfunctionasync1(){console.log('async1start')awaitasync2()console.log('async1end')}asyncfunctionasync2(){console.log('async2')}console.log('script开始')setTimeout(function(){console.log('setTimeout0')},0)setTimeout(function(){console.log('setTimeout3')},3)setImmediate(()=>console.log('setImmediate'));process.nextTick(()=>console.log('nextTick'));async1();newPromise(function(resolve){console.log('promise1')resolve();console.log('promise2')}).then(function(){console.log('promise3')})console.log('scriptend')正确输出面试题脚本startasync1startasync2promise1promise2scriptendnextTickasync1endpromise3setTimeout0setImmediatesetTimeout3理解节点提问.关于js的异步,有一些地方不是很理解。使用node.js的开发者一定知道,它是一种单线程、异步、非阻塞、高并发的语言。异步任务启动时,是简单到谁先完成,还是异步任务最后有执行顺序?单线程异步语言如何实现高并发?接下来让我们带着这两个问题来真正理解node.js中的异步(microtask和eventloop)。Node的异步语法比浏览器的更复杂,因为它可以与内核对话,所以必须构建一个特殊的库libuv来做这件事。这个库负责各种回调函数的执行时间。最后,基于事件循环机制,异步任务必须返回主线程,并逐一排队执行。详解1、当前周期和第二周期的异步任务可以分为两种。TheasynchronoustaskappendedtothecurrentcycleTheasynchronoustaskappendedtonextcycle所谓“周期”,就是指事件循环(eventloop)。这就是JavaScript引擎处理异步任务的方式,后面会详细解释。这里只要理解,当前循环肯定比第二个循环早执行。Node规定process.nextTick和Promise的回调函数加入到当前循环中,即一旦同步任务执行完毕,就会执行。setTimeout、setInterval、setImmediate的回调函数是在第二个循环中加入的。2.process.nextTick()1)process.nextTick不要因为有next就被很多朋友认为是第二个循环。2)Node执行完所有同步任务后,接下来会执行process.nextTick的任务队列。3)开发过程中如果想尽快执行异步任务,可以使用process.nextTick来完成。3.Microtack根据语言规范,Promise对象的回调函数会进入异步任务中的“microtask”队列。microtask队列加在process.nextTick队列后面,也是属于当前循环。根据语言规范,Promise对象的回调函数会进入异步任务中的“微任务”(microtask)队列。microtask队列加在process.nextTick队列后面,也是属于当前循环。所以,下面的代码总是先输出3,再输出4。process.nextTick(()=>console.log(3));Promise.resolve().then(()=>console.log(4));//输出结果3,4process.nextTick(()=>console.log(1));Promise.resolve().then(()=>console.log(2));process.nextTick(()=>console.log(3));Promise.resolve()。then(()=>console.log(4));//输出结果1,3,2,4注意,只有前一个队列完全清空后,才会执行下一个队列。两个队列的概念是nextTickQueue和microTaskQueue。也就是说,有几种类型的异步任务,比如promise对象,但是对于队列之间的不同任务,还是会有顺序的,这个顺序是由队列决定的。4.事件循环的阶段(idle,prepare忽略这个阶段)最详细的事件循环在最阶段的解释(官网:https://nodejs.org/en/docs/gu...)的timers阶段包括setTimeout()和setInterval()IO回调大部分的回调事件,常见的caollbackpoll阶段网络连接、数据获取、读取文件等操作check阶段setImmediate()调用callback,close阶段有一些关闭回调,比如socket。on('close',...)eventloop注1)当Node开始执行脚本时,会先初始化eventloop,但是eventloop还没有开始,下面的事情会先完成。同步任务发送异步请求,规划定时器生效的时间,执行process.nextTick()等。最后,上面的事情都做完了,事件循环正式开始。2)事件循环也是在单线程环境下运行的。高并发还依赖于事件循环。每产生一个事件,都会加入到这个阶段对应的队列中。这时,事件循环会取出队列中的事件,准备执行。打回来。3)假设现在事件循环已经进入到某个阶段,即使在此期间有其他队列中的事件就绪,在进入下一阶段之前,也会执行完当前队列的所有回调方法。5、事件循环中的setTimeOut和setImmediate是在timers阶段执行的,因为setTimeout是执行的,而setImmediate是在check阶段执行的。因此,setTimeout将比setImmediate更早完成。setTimeout(()=>console.log(1));setImmediate(()=>console.log(2));上面的代码应该是先输出1,再输出2,但是实际执行的时候,结果是不确定的,有时会先输出2,再输出1。这是因为setTimeout的第二个参数默认为0。但实际上Node并不能要达到0毫秒,至少需要1毫秒。根据官方文档,第二个参数的取值范围在1毫秒到2147483647毫秒之间。也就是说,setTimeout(f,0)等同于setTimeout(f,1)。在实际执行中,进入事件循环后,可能是1毫秒,也可能不是1毫秒,取决于当时系统的状态。如果小于1毫秒,则跳过timers阶段,进入check阶段,先执行setImmediate的回调函数。但是下面的代码必须先输出2,再输出1。constfs=require('fs');fs.readFile('test.js',()=>{setTimeout(()=>console.log(1));setImmediate(()=>console.log(2));});上面的代码会先进入I/O回调阶段,然后是check阶段,最后是timers阶段。所以setImmediate会比setTimeout早执行。6、同步任务中async和promise的一些误解问题一:面试题中,在同步任务的过程中,不知道大家有没有疑惑。为什么执行async2输出后不执行async1end输出,而是执行promise1?引用阮一峰老师书上的一句话:“async函数返回一个Promise对象,函数执行时,一旦遇到await就先返回,触发的异步操作执行完毕后,再在函数体中执行下面的语句完全的。”简单来说就是先执行下面的同步任务代码,执行完成后,即表达式中的Promise解析完成后,继续执行async函数,返回解析结果。(其实还是当前周期的promise有问题,最终的resolve是异步的,位于当前周期的末尾。)问题2:为什么console.log('promise2')先于resolve执行?答:注:本内容出处为阮一峰老师编写的ES6书籍。调用resolve或reject不会终止promise的参数函数的执行。因为立即解析的Promise是在当前周期结束时执行的,它总是晚于当前周期的同步任务。正式的写法调用resolve或reject后,Promise的使命就完成了,后面的操作应该放在then方法之后。所以最好在前面加上return语句,这样就不会出现意外newPromise((resolve,reject)=>{returnresolve(1);//后面的语句不会执行console.log(2);}问题三:promise3和scriptend的执行顺序有没有疑问?答:因为立即resolved的Promise是在当前循环结束时执行的,总是晚于本次循环的同步任务当前周期。promise是一个立即执行函数,但是他的成功(或失败:reject)回调函数resolve是一个异步执行回调,当resolve()执行时,任务会被放入回调队列,等待事件循环当调用堆栈空闲时获取并执行它。在这个循环中执行的最后一个。整体结论顺序的整体概括为:同步任务->当前周期->第二个周期附件:参考node.js官网:事件周期:https://nodejs.org/en/docs/gu...Timers:https://nodejs.org/dist/lates...加入我们一起学习!节点学习交流群交流群成员超过100人,无法自动入群。请加群助手微信号:[coder_qi]备注节点,会自动拉你入群。
