




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】如何在微信小程序中使用async或await?
微信小程序中有大量接口是异步调用,比如wx.login()、wx.request()、wx.getUserInfo()等,都是使用一个对象作为参数,并定义了success()、fail()和complete()作为异步调用不同情况下的回调。但是,以回调的方式来写程序,真的很伤,如果有一个过程需要依次干这些事情:那么,代码大概会长这样wx.getStorage({
fail:()=>{
wx.getSetting({
success:settings=>{
wx.login({
success:({code})=>{
wx.getUesrInfo({
code,
success:(userInfo)=>{
wx.request({
success:()=>{
//dosomething
}
});
}
});
}
});
}
});
}
});显然,async/await可以同样逻辑的代码看起来舒服得多。不过默认情况下,“微信开发者工具”并不支持async/await。如何启用?1.用上async/await如果有心,在微信小程序官方文档中搜索async可以找到“工具⇒开发辅助⇒代码编译”页面中提到了对async/await的支持情况,是在“增加编译”小节的一个表格中,摘录一段:在1.02.1904282以及之后版本的开发工具中,增加了增强编译的选项来增强ES6转ES5的能力,启用后会使用新的编译逻辑以及提供额外的选项供开发者使用。特性原有逻辑增强编译Async/Await不支持支持支持async/await语法,按需注入regeneratorRuntime,目录位置与辅助函数一致在1.02.1904282以及之后版本的开发工具中,增加了增强编译的选项来增强ES6转ES5的能力,启用后会使用新的编译逻辑以及提供额外的选项供开发者使用。总之呢,就是,只要把“微信开发者工具”更新到v1.02.1904282以上,就不需要干npminstallregenerator这之类的事情,只需要修改一个配置项就能使用async/await特性了。这个配置就在“工具栏⇒详情⇒本地设置”页面中。为了快速验证async/await可用,在app.js的onLaunch()事件函数中加一段代码:(async()=>{
constp=awaitnewPromise(resolve=>{
setTimeout(()=>resolve("helloasync/await"),1000);
});
console.log(p);
})();在短暂的自动编译运行之后,在调试器界面的Console页签中可以看到输出:helloasync/await如果不行,请先检查“微信开发者工具”的版本——至少,去下载一个最新版本总不会有问题的。2.改造wx.abcd异步方法虽然async/await得到了支持,但是还得把wx.abcd()封装成Promise风格才行。Node.js在util模块中提供了promisify来把Node.js风格的回调转换成Promise风格,但显然它不适用于wx风格。还是自己动手吧,也不用考虑太多,比如wx风格的异步调用在形式上都是一致的,它们的特征如下:所以,如果wx.abcd()改成了Promise风格,通过async/await来编写,大概应该是这个样子try{
constres=wx.abcd();
//doanythinginsuccesscallback
}catch(err){
//doanythinginfailcallback
}finally{
//doanythingincompletecallback
}当然,catch和finally这两个部分并不是必须,也就是说,不一定非得用try语句块。但是,如果不用catch,会有一个神坑存在,这个问题后面再说。现在首先要做的是改造。2.1.定义promisify()promisify()就是一个封装函数,传入原来的wx.abcd作为参加,返回一个Promise风格的新函数。代码和解释如下:由于51cto博客在显示代码时,部分字体不是等宽字体,纯代码张贴出来的标记不能对准,所以先贴图。但为了方便试验,接着贴代码。由于51cto博客在显示代码时,部分字体不是等宽字体,纯代码张贴出来的标记不能对准,所以先贴图。但为了方便试验,接着贴代码。functionpromisify(fn){
//promisify()返回的是一个函数,
//这个函数跟传入的fn(即wx.abcd)签名相同(或兼容)
returnasyncfunction(args){
//
^^^^接受一个单一参数对象
returnnewPromise((resolve,reject)=>{
//
^^^^^^^^^^^返回一个Promise对象
fn({
//
^^^调用原函数并使用改造过的新的参数对象
...(args||{}),
//
^^^^^^^^
这个新参数对象得有原本传入的参数,
//
^^
当然得兼容没有传入参数的情况
success:res=>resolve(res),
//
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
注入success回调,resovle它
fail:err=>reject(err)
//
^^^^^^^^^^^^^^^^^^^^^^^^注入fail回调,reject它
});
});
};
}举例使用它:constasyncLogin=promisify(wx.login);
//注意别写成wx.login(),为什么,我不说
try{
constres=asyncLogin();
constcode=res.code;
//dosomethingwithcode
}catch(err){
//loginerror
}finally{
//promisify里没有专门注入complete回调,
//因为complete的内容可以写在这里
}2.2.定义wx.async()不过老实说,把要用的异步方法通过promisify一个个处理,写起来还是挺烦的,不如写个工具函数把要用的方法一次性转换出来。不过一查,wx下定义了不知道多少异步方法,还是退而求其次,用到啥转啥,不过可以批量转,转出来的结果还是封装在一个对象中。整个过程就是迭代处理,最后把每个处理结果聚焦在一起:functiontoAsync(names){
//这里names期望是一个数组
return(names||[])
.map(name=>(
{
name,
member:wx[name]
}
))
.filter(t=>typeoft.member==="function")
.reduce((r,t)=>{
r[]=promisify(wx[]);
returnr;
},{});
}这个toAsync的用法大致是这样的constawx=toAsync(["login","request"]);
awaitawx.login();
awaitawx.request({...});有些人可能更习惯单个参数传入的方式,像这样constawx=toAsync("login","request");那么在toAsync的定义中,参数改为...names就好,即functiontoAsync(...names){...}还没完,因为我不想在每一个JS文件中去import{toAsync}from...。所以把它在App.onLaunch()中把它注入到wx对象中去,就像这样App({
onLaunch:function(){
//...
wx.async=toAsync;
//...
}
});3.await带来的神坑工具准备好了,代码也大刀阔斧地进行了改造,看起来舒服多了,一运行却报错!为什么???先来看一段原来的代码,是这样的wx.getStorage({
key:"blabla",
success:res=>{
//dowithres
}
});改造之后是这样constres=awaitawx.getStorage({key:"blabla"});
//<==runtimeerror
//dowithresawx.getStorage抛了个异常,原因是叫"blabal"的这个数据不存在。为什么原来没有错,现在却报错?因为原来没有定义fail回调,所以错误被忽略了。但是promisify()把fail回调封装成了reject(),所以awx.getStorage()返回的Promise对象上,需要通过catch()来处理。我们没有直接使用Promise对象,而是用的await语法,所以reject()会以抛出异常的形式体现出来。用人话说,代码得这样改:try{
constres=awaitawx.getStorage({key:"blabla"});
//<==runtimeerror
//dowithres
}catch(err){
//我知道有错,就是当它不存在!
}伤心了不是?如果没有伤心,你想想,每一个调用都要用try...catch...代码块,还能不伤心吗?3.1.忽略不需要处理的错误处理错误真的是个好习惯,但真的不是所有错误情况都需要处理。其实要忽略错误也很简单,直接在每个Promise形式的异步调后面加句话就行,比如constres=awaitawx
.getStorage({key:"blabla"})
.catch(()=>{});
//
^^^^^^^^^^^^^^^^捕捉错误,但什么也不干稍微解释一下,在这里awx.getStorage()返回一个Promise对象,对该对象调用.catch()会封装reject的情况,同时它会返回一个新的Promise对象,这个对象才是await等待的Promise。不过感觉.catch(()=>{})写起来怪怪的,那就封装成一个方法吧,这得改Promise类的原形Ptot
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 教师结对对帮扶协议书
- 环评意向协议书
- 电脑版权协议书
- 荒地买卖协议书
- 外部合伙人合同协议书
- 签订主仆协议书
- 聘请销售协议书
- 配件质保协议书
- 退造林押协议书
- 贷款联保协议书
- 【MOOC】食品微生物学-北京林业大学 中国大学慕课MOOC答案
- 中国慢性阻塞性肺疾病基层诊疗指南(2024年)解读
- 《阻燃材料与技术》课件 第3讲 阻燃基本理论
- 公务员个人自传3000字【公务员个人自传格式】
- 盆腔淋巴漏的护理
- 阿拉伯帝国课件
- NCR-333航行警告仪操作指南
- 生物安全记录表
- 2024年江苏省淮安市中考英语试题卷(含答案解析)
- 新时代大学英语泛听教程1 课件汇 U5 Love and Romance- U8 Shopping
- 2024年高考真题-英语(全国甲卷) 含答案
评论
0/150
提交评论