详细说明在ES7中使用Await减少回调嵌套的方法
序
我们知道javascript是不能被阻塞的,所有的等待都只能通过回调来完成,这就造成了回调的嵌套问题,导致代码混乱,所以此时Await是有用的。
这里不详细描述await的底层机制,以免把文章的长度拖得很长。需要的朋友可以参考本文://www . JB 51 . net/article/123257 . htm,本文的正式内容将从下面开始。
用Await减少回调嵌套
我们在开发的时候,有时候需要发送大量的请求,然后经常会面临嵌套回调的问题,也就是回调中嵌入了一个回调,导致代码严重缩进。
如以下代码所示:
ajax({ url: '/list ',type: 'GET ',success:函数(数据){ appendToDOM(数据);ajax({ url: '/update ',type: 'POST ',success:函数(数据){ util.toast('Success!');}) });}});这种代码似乎有点难,这种异步回调通常可以用Promise进行优化,上面的代码可以改为:
new Promise(resolve={ Ajax({ URL : '/list '),type: 'GET ',success : data=resolve(data);})}).然后(data={ appendToDOM(数据);ajax({ url: '/update ',type: 'POST ',success:函数(数据){ util . toast(' success!');}) });});Promise提供了一个解析,当异步结束时可以方便地通知,但是本质是一样的,回调仍然被使用,但是这个回调放在了那时。
当需要多次获取异步数据时,可以使用Promise.all来解决这个问题:
let order Promise=new Promise(resolve={ Ajax('/order ',' GET ',data=resolve(data));});让user Promise=new Promise(resolve={ Ajax('/user ',' GET ',data=resolve(data));});Promise.all([orderPromise,userPromise])。然后(values={ let order=values[0],user=values[1];});但是这里也使用回调。有没有优雅的解决方案?
ES7的Await/async可以使异步回调编写与同步代码相同的方式。第一个嵌套回调示例可以从wait更改为以下代码:
//使用await获取异步数据让lead list=wait new promise(resolve={ Ajax({ URL : '/list '),type:' get ',success : data=resolve(data);});});//await使代码自然地像瀑布一样编写,appendToDom(lead list);ajax({ url: '/update ',type: 'POST ',success :()=util . toast(' success ');});wait允许像瀑布一样自然地编写代码。
第二个例子:多次获取异步数据,可以更改如下:
let order=wait new Promise(resolve=Ajax('/order ',data=resolve(data))),user=wait new Promise(resolve=Ajax('/user ',data=resolve(data)));//做某事。用order/user就像在本地获取数据一样,所以不需要设置回调函数。
Await不仅用于发送请求,还适用于其他异步场景。比如在创建订单之前,我先玩一个小盒子,问用户要创建什么样的订单,然后再玩设置订单的盒子。因此,按照正常的思维,这里需要传递一个按钮回调的click函数,如下图所示:
但是它可以通过await来解决,如下面的代码所示:
让quoteHandler=require('。/quote ');//弹出框询问用户,得到用户的选择。让创建类型=等待报价处理程序。确认创建();报价返回承诺,监控点击事件,并传递创建类型:
let quote handler={ confirm create : function(){ dialog . showdialog({ contenttpl : TPL,class name : ' confirm-create-quote ' });让$quoteDialog=$('。确认-创建-报价表单')[0];返回新的Promise(解析={ $(form.submit))。on('click '),function(event){ resolve(form . createtype . value);});});}}以便外部调用方可以使用await,而不是为click事件传递回调函数。
然而,我们应该注意等待的一次性执行特征。与回调函数相比,await的执行是一次性的,比如你听了click事件,然后用了await,那么click事件只会执行一次。因为代码是从上到下执行的,所以如果您想在单击后继续修改和提交,就不能使用await。此外,您可以使用await来获取异步数据。如果出了问题,成功的解析不会被执行,后续的代码也不会被执行,所以请求出错的时候基本逻辑不会出错。
要在巴别塔中使用await,您需要:
(1)安装节点包
NPM安装-保存-devbabel-plugin-transform-async-to-generator(2)在项目的根目录下添加一个. babelrc文件,内容为:
{ ' plugins ' :[' transform-async-to-generator ']}(3)在使用模块时首先介绍它
require(' babel-poly ill ');然后你可以愉快地使用ES7的等待。
需要使用await在函数前面添加Async关键字,如下所示:
Async showOrderDialog() {//获取创建类型让创建类型=await quotehandler。确认创建();//获取旧订单数据让订单信息=等待订单处理程序. order data}我们再举一个例子:使用await实现JS版本的sleep函数,因为原生不提供线程sleep函数,如下面的代码所示:
函数sleep (time) {返回新的Promise(resolve=setTimeout(()=resolve(),time));}async函数start(){ await sleep(1000);} start();Babel的await实现被转换为ES6生成器,具有以下关键代码:
while(1){ switch(_ context . prev=_ context . next){ case 0: _ context . next=2;//sleep返回一个Promise对象返回sleep(1000);case 2: case ' end ' : return _ context . stop();}}而巴贝尔的生成器也是要用ES5来实现的。什么是发电机?如下图所示:
生成器由函数*定义,每次执行生成器的下一个函数时,都会返回当前生成器中yield返回的值,然后生成器的迭代器会后退一步,直到完成所有yield。
感兴趣的可以继续研究巴别塔如何将ES7转化为ES5。据说原生实现直接基于Promise。
使用await的另一个优点是,您可以直接尝试捕获异步进程引发的异常,因为我们不能直接捕获异步回调中的异常,如下所示:
让quote handler={ confirm create : function(){ $(form。提交)。on ('click ',function(event){//这里将抛出一个未定义的异常:value属性回调(form。未定义的notfoundinput.value)被访问;});} }尝试{//此处无法捕获quoteHandler.confirmCreate()异常;} catch (e) {}上面的try-catch是没有办法捕捉异常的,因为try中的代码已经被执行了,而且在执行的过程中也没有异常,所以这里无法捕捉。如果你使用诺言,你通常使用诺言链的捕捉:
让quote handler={ confirm create : function(){返回新的Promise(resolve={ $(form.submit))。on('click ',Function(event){ //这里会抛出一个未定义的异常:访问undefined的value属性进行解析(form。notfoundinput . value);});});}} quotehandler。确认创建()。然后(创建类型={})。catch(e={//异常可以在这里捕捉到});有了await,我们可以直接使用同步捕获,就好像它真的变成了同步执行:
尝试{ create type=wait quote handler . confirm create(' order ');} catch(e){ console . log(e);返回;}总之,使用await让代码编写的嵌套少了很多,便于逻辑处理,享受丝滑流畅。
摘要
以上就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。有问题可以留言交流。谢谢你的支持。
版权声明:详细说明在ES7中使用Await减少回调嵌套的方法是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。