JS异步笔记
Promise
最早接触异步是在.net中,当时还是比较流行使用基于控件的BackgroundWorker
,其自身通过子线程的方式来异步处理一些情况,并且封装了一些功能与主线程通信。后来,开始使用Thread,再后来,因为Thread的性能与生成数量的不可控,使用了ThreadPool,再后来,出现了Task,随后async、await如发而至。在理解了async和await之后不久,es2015便为js也带来了Promise,以解决在js中大量的callback的问题(说实话,在层数不多的情况下,用callBack还是很爽的,可能年纪大了,思维有些固守了)。Promise使得无处不在的callBack得到了控制,阅读追踪代码也终于变得方便了。
关于Promise,可以参考其白皮书https://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects
,在MDN上,给出的使用方法是
var DoWork=new Promise( function(resolve, reject) {...} /* executor */ );
其中,resolve和reject也是回调函数(callback),并且在{...}的语法块中,如果一切正常则调用resolve回调方法返回,如果有问题,则调用reject回调方法返回。这像极了原来的回调方式(如function DoWork(SuccessCallBack,ErrorCallBack){...}。但是,其最大的特点则在于,返回的并不是function
了,而是一个Promise
对象,这也为以后的await的加入铺好了路。同样,在调用的时候,语法糖也甜得很。
原本DoWork的调用方法:
DoWork(()=>{alert("success");},err=>{ alert("fail");});
新的调用方法:
DoWork().then(()=>{alert("success");}).catch(err=>{alert(err);});
想来,聪明的你,并没有发现这种用法的场景中,有何优势。当然,优势还是有的,比较在使用Promise.All()函数的时候,则可以使得多个并发任务同时执行,只有在每一个任务都完成的情况下,才执行then的后续方法。另外,写法上,将之前的内层嵌套改为现在的外层用.的链式调用,在美观和可读性上,提升了不少,还有其它一些优势,这里就不多说了,因为今天Promise不是主角,它只是主角的爹妈,,而主角则是async/await
。
async/await
做了这么多年的c#开发,微软给我的最大感觉的就是,语法糖真的甜。之前遇到一个微信的开发框架Senparc.Weixin SDK
也是同样的开发理念,说实话,真的好,能让开发人员少写一行就绝不让多写一行,能让开发人员少动脑子就不让其多动脑子,这样,可以有更大的精力放在处理业务以及构造程序逻辑关系上。js的`async/await和.net的非常像,这里就不说.net了,只说js中
async/await`的用法。
对于async/await
(打起来好烦,下文就用aa表示了(冰魂:……))来说,它最大的优势在于,可以以同步代码的方式来实现异步,并且与人的自然认识非常的吻合。
举个例子:
1、给小明钱。
2、让小明去超市买西瓜,如果有西瓜就买回来,如果没有,则买苹果,如果苹果也没有,就把钱还给我。
3、给小丽个椅子。
4、让小丽在这儿看电视。
var XiaoMingGoToMarket = return Promise(resolve,reject=>{
setTimeout(()={
if(有西瓜()){
resolve("买了西瓜");
}else if(有苹果()){
resolve("买了苹果");
}else{
reject("啥也没买,钱还给你吧");
}
},5*1000);//五分钟后到超市
async function MakeXiaoMingToMarket(){
console.log("知道了,现在就准备去超市");
try{
var 买的水果= await XiaoMingGoToMarket();
console.log("买到了"+买的水果);
}catch(err){
console.log("啥也没买到,"+err);
}
}
console.log('1、给小明钱');
console.log("2、让小明去超市买西瓜,如果有西瓜就买回来,如果没有,则买苹果,如果苹果也没有,就把钱还给我");
MakeXiaoMingToMarket();
console.log('3、给小丽个椅子。');
console.log('4、让小丽在这儿看电视。');
以上代码,先不看XiaoMiGoToMarket
这个定义,下面的五行代码就非常的接近人的思维,其主体是我,我在一件件的下命令,至于客体要怎么做,什么时候去做我不管。对于我来讲,这五行代码是同步的,有严格的先后顺序,因为“我”下命令本身就是有先后的。但是,在我下指令给小明让小明去做事情 的时候,它去超市这段在路上的时间,是异步的。所以,对于小明来说,他的事情分为三部分(不考虑回来的事情):1、接收我的指令。2、走在路上(比较耗时)。3、到了超市买东西并告诉我结果。其中,接收我的指令是与我直接相关的,我需要知道他是否真的接收到我的指令了,所以,与我是同步的。在他接收到我的指令之后 ,我再给小丽一个椅子(不然,估计我就自己亲自去买了)。这是小明的第一部分做的事情,其第二部分,则是await那一句,那一句,则是产生异步的开始,await其实就是小明去买水果了,同时,离开我的视线,我与他的同步关系也就断开了,我开始“给小丽个椅子”了,然后继续做我自己的事情。至于小明,等他的await的事情(去超市买东西)完成了之后,他会接着await下面的语句,将下面的事情做完。
大概就是这么个过程,其实原理很简单。
就是:
1、async function会被拆成两份,以await语法分开,之前一部分(不包含await本身),我们称它为PreWork,之后一部分我们你之为AftWork。
2、PreWork是同步代码,和非async的function中的代码一样,与调用函数同步。
3、当函数插到await,即AftWork代码时,因为await后面跟着的是Promise,所以,此时,异步执行Promise,同时,将AftWork打包为一个函数,放在旁边。同时,调用方法的执行焦点,从async function中返回,继续去执行自己的代码。
4、当await后面的Promise执行完成后,如果其内部调用了resolve,则执行之前放在旁边的由AftWork打包的一个临时函数。如果其内部调用了reject,则在await这一句这儿,向外抛出一个异常,其异常内容为reject(err)时其参数的内容。
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/17745765.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!