当前位置: 首页 > 后端技术 > Node.js

Promise&&async-await的理解和使用

时间:2023-04-03 19:35:47 Node.js

Promise&&async/await的理解和使用。性和调试的难度会增加很多;如何理解promise想象一下,你把一个任务交给一个好人,他叫做promise;不用担心你交给他的任务丢了,他总会回来的,而且是resolve成功,reject失败;varpromise=newPromise((resolve,reject)=>{//将一个异步任务交给“promise”同学setTimeout(()=>{if(true){//成功,返回paramsresolve('params')}else{//失败,返回错误reject('error')}},1000)})//上面是promise一个任务,下面是promise.then((res)=>{console.log(res)}).catch((rej)=>{console.log(res)})如何使用promise实际情况下,异步场景并没有那么简单,你可能会遇到Letpromise=newPromise((res,rej)=>{asyncFunc('promise',1000,res,rej)})promise.then(res=>{console.log(res);returnnewPromise((res,rej)=>{asyncFunc('second',2000,res,rej)})}).then(res=>{console.log(res);returnnewPromise((res,rej)=>{asyncFunc('third',1000,res,rej)})//throw'oh,no!';}).then(res=>{console.log(res);console.log('endinggggggg')}).catch(err=>{console.log('catch',err)})《并行应用场景》处理方案(即所有异步操作完成后执行)letpromise1=newPromise((res,rej)=>{asyncFunc('promise1',1000,res,rej)})letpromise2=newPromise((res,rej)=>{asyncFunc('promise2',2000,res,rej)})letpromise3=newPromise((res,rej)=>{asyncFunc('promise3',1000,res,rej)})varpromiseAll=Promise.all([promise1,promise2,promise3])promiseAll.then(res=>{console.log('最后的结果',res)}).catch(err=>{console.log('catch',err);})"inracingmode",如字面意思,只要提前完成表示整个状态处理完成;这个场景可以发散为如果超过3s,我就不做这件事letpromise1=newPromise((res,rej)=>{asyncFunc('promise1',1000,res,rej,true)})letpromise2=newPromise((res,rej)=>{asyncFunc('promise2',2000,res,rej,true)})letpromise3=newPromise((res,rej)=>{asyncFunc('promise3',1000,res,rej)})//1000s任务完成,直接返回promise1即可varpromiseRace=Promise.race([promise1,promise2,promise3])promiseRace.then(res=>{console.log('finalresult',res)}).catch(err=>{console.log('catch',err);})js是单线程的,promise,setTimeout的执行优先级是关于这块我们不得不说的事件nodejs的处理机制;事件队列应该是一个数据结构,所有的东西都在事件循环中排队处理,直到队列为空。但是Node中的这种情况与抽象反应器模式描述的方式有很大不同。以下内容仅适用于V8;NodeJS中有很多队列,不同类型的事件在它们自己的队列中排队。在处理完一个阶段后,在进入下一个队列之前,事件循环将处理两个中间队列,直到中间队列中没有剩余的项目。定义:主要有四种类型,由libuv事件循环处理;过期定时器和间隔队列——(比如使用setTimeout、setInterval);IOeventqueue-完成的IOeventImmediatesqueue-使用setImmediate函数添加回调closehandlerQueues-任何closeeventhandlers也有2个中间队列,不是libuv本身的一部分,而是nodejs的一部分;NextTicksQueue-使用process.nextTick函数添加回调;(higherpriority)othermicrotaskqueues-包括其他微任务,比如resolvedpromisecallbacks;工作原理:上图是node处理异步I/O操作的libuv模块流程图;Node通过使用timers检查队列中任何过期的计时器来启动事件循环,并在每一步迭代每个队列。如果没有任务,则循环退出,并且每个队列事务都被视为事件循环的一个阶段。特别有意思的是中间的红色队列,每个stage都会优先处理中间队列的任务。然后去其他队列。什么是async/awaitasync/await,可以通过Generator和promise的结合来实现;注意核心点:asnyc函数总是返回一个Promise对象,不管函数是否返回Promise;await后面跟着一个Promise对象,如果不是Promise对象,也会被封装成为一个Promise;async/await和Promise对象本质上是一样的。其他注解点等待的任何内容都通过Promise.resolve()传递,这样就可以安全地等待非原生的Promises;构造函数和getter/settings方法不能是异步的;即使写了同步代码,也不要错过并行执行的机会,否则需要消耗等待的性能损失;BabelREPL说起来很有意思。试试吧。如何使用async/await实际情况下,异步场景并没有那么简单,你可能会遇到如下场景:只有一个await和resolveconstdelay=timeout=>newPromise(resolve=>setTimeout(resolve,timeout));异步函数f(){等待延迟(1000);等待延迟(2000);等待延迟(3000);返回'??完成'}f().then(v=>console.log(v));场景:只有一个await和rejectleta;asyncfunctiong(){awaitPromise.reject('error');a=await1;}g().then(v=>console.log(v)).catch(err=>console.log(err));场景:有多个等待,可以使用try/catchleta;asyncfunctiong(){try{awaitPromise.reject('error')}catch(err){console.log(err)}a=await1;返回a;}g().then(v=>console.log(v)).catch(err=>console.log(err));场景:等待并行任务asyncfunctionseries(){constawait1=delay(1000);constawait2=延迟(1000);等待等待1;等待等待2;返回“完成”}系列();欢迎评论和star。如果有不对的地方,觉得有帮助可以提issue可以stargithub参考文档。这个系列的文档很好https://juejin.im/post/5b777f...说说promise,setTimeout优先级;不dejs中事件循环中的任务优先级https://jsblog.insiderattack....developers.google.com域名下的文档还是很优质的,会比较全面的介绍如何使用promise和异步/等待https://developers.google.com...