要理解JS中的异步和同步,需要了解JS代码和EventLoop的执行过程。JavaScript代码在执行过程中,程序需要执行的操作都会被放入调用栈(ALIFO(LastIn,FirstOut)栈),一种先进后出的数据结构。constbar=()=>console.log('bar')constbaz=()=>console.log('baz')constfoo=()=>{console.log('foo')bar()baz()}foo()当这段代码执行时,首先会调用foo()。在foo()内部首先调用bar(),然后是baz()。此时的CallStack是这样的:每执行一个操作,就将一个新的操作压入栈顶,执行完后从栈顶弹出,直到整个栈变为Empty。EventLoop的作用是每次迭代都会回过头来检查CallStack中是否有要执行的指令,然后执行。JavaScript中的异步和同步代码执行在大多数情况下,JavaScript是同步执行代码的:letlog=console.log;让一个=5;让b=50;leta1=function(){return5}letb1=function(){return50}log(a1())log(a2())leta2=function(num){return5*num}letb2=function(){return50}log(a2(b2))//打印出来://5//50//250异步执行的代码setTimeout,callbacks,Promise,fetch,ajax,filesysteminteraction,databasecalls,DOMeventlistener以上代码将异步执行。原因是代码在执行这些方法的时候,并不确定需要多长时间才能完成对应的操作,所以会继续往下执行。考虑以下情况:leta3=100;setTimeout(function(){a3++},0);log(a3)setTimeout(function(){log(a3)},0);//打印出来//100//101同步代码放入CallStack执行,异步代码放入一个队列(MessageQueue)。EventLoop会优先执行CallStack中的任务,当CallStack为空时,它会执行MessageQueue中的任务。ES6JobQueueECMAScript2015引入了Promises使用的JobQueue的概念。它会导致异步方法的结果尽快被执行,而不是放在CallStack的末尾。Promises是一个非常好的异步实现:constbar=()=>console.log('bar')constbaz=()=>console.log('baz')constfoo=()=>{console.log('foo')setTimeout(bar,0)newPromise((resolve,reject)=>resolve('应该在baz之后,bar之前')).then(resolve=>console.log(resolve))baz()}foo()//foo//baz//应该在baz之后,bar之前//bar可以看到Promise会在setTimeout之前执行。看看这段代码,如何判断它的执行顺序呢?console.log(1);setTimeout(()=>console.log(2));Promise.resolve().then(()=>console.log(3));Promise.resolve().then(()=>setTimeout(()=>console.log(4)));Promise.resolve().then(()=>console.log(5));setTimeout(()=>console.log(6));console.log(7);//1//7//3//5//2//6//4NodejsProcess.NextTick()和SetImmediate()Process.NextTick()会在最后一个通过该方法可以实现循环的执行,异步方法尽快执行,而不是放入异步队列。Process.NextTick回调函数会被添加到Process.NextTick队列,Promise.Then()会被添加到Promises微任务队列(MicrotaskQueue),SetTimeout,SetImmediate会被添加到宏任务队列(MacrotaskQueue)。延迟0ms的SetTimeout()的异步和SetImmediate()非常相似,都是在下一个事件循环中执行。事件循环首先执行Process.NextTick队列,然后是Promises微任务队列,然后是宏任务队列。console.log('scriptstart');//异步Promise.resolve().then(function(){console.log('promise');}).then(function(){console.log('promise-then');});//异步setImmediate(function(){console.log('setImmediate')})//异步setTimeout(function(){console.log('setTimeout0')},0)//异步setTimeout(function(){returnnewPromise(resolve=>{console.log('setTimeout-delay100mspromise')resolve()}).then(res=>{console.log('setTimeout-delay100mspromise.then')})},100)process.nextTick(function(){console.log('process.nextTick')})console.log('scriptend');/*scriptstartscriptendprocess.nextTickpromisepromise-thensetTimeout0setImmediatesetTimeout-delay100mspromisesetTimeout-delay100mspromise.then*/参考链接https://nodejs.dev/en/learn/t...文章首发于IICOOM-个人博客|技术博客《JavaScript中的异步、同步》
