微信小程序中使用Promise进行异步流程处理的实例详解


Posted in Javascript onAugust 17, 2017

微信小程序中使用Promise进行异步流程处理的实例详解

我们知道,JavaScript是单进程执行的,同步操作会对程序的执行进行阻塞处理。比如在浏览器页面程序中,如果一段同步的代码需要执行很长时间(比如一个很大的循环操作),则页面会产生卡死的现象。

所以,在JavaScript中,提供了一些异步特性,为程序提供了性能和体验上的益处,比如可以将代码放到setTimeout()中执行;或者在网页中,我们使用Ajax的方式向服务器端做异步数据请求。这些异步的代码不会阻塞当前的界面主进程,界面还是可以灵活的进行操作,等到异步代码执行完成,再做相应的处理。

一段典型的异步代码类似这样:

function asyncFunc(callback) {
 setTimeout(function () {
  //在这里写你的逻辑代码
  //...

  //逻辑代码结束,执行一个回调函数
  callback();
 }, 5000);
}

或者:

function getAccountInfo(callback, errorCallback) {
 wx.request({
  url: '/accounts/12345',
  success: function (res) {
   //...
   callback(data);
  },
  fail: function (res) {
   //...
   errorCallback(data);
  }
 });
}

然后我们这样调用:

asyncFunc(function () {
 console.log("asyncFunc() run complete");
});

getAccountInfo(function (data) {
 console.log("get account info successfully:", data);
}, function () {
 console.error("get account info failed");
});

这是一种使用了回调函数来控制代码执行流程的方式。这样看起来没问题,也挺容易理解。

但是,如果我们一段代码中,异步操作太多,又要保证这些异步操作是有顺序的执行,那我们的代码就看起来非常糟糕,就像这样:

asyncFunc1(function(){
 //...
 asyncFunc2(function(){
  //...
  asyncFunc3(function(){
   //...
   asyncFunc4(function(){
    //...
    asyncFunc5(function(){
      //...
    });
   });
  });
 });
});

这样的代码可读性和可维护性可想而知了。还有,回调函数真正的问题在于:

它剥夺了我们使用 return 和 throw 这些关键字的能力。

那有什么办法来改善这个问题呢?答案是肯定的,Promise这种概念的产生,很好地解决了这一切。关于什么是Promise,一搜一大把介绍,我这里就不复制粘贴了,我主要是讲一下我们怎么用它来解决我们的问题。

我们来看一下,上面的例子如果使用Promise,它会是什么样子?我们先将这些函数变成Promise的方式:

function asyncFunc1(){
 return new Promise(function (resolve, reject) {
  //...
 })
}

 
// asyncFunc2,3,4,5也实现成跟asyncFunc1一样的方式...

然后看一下他们是怎么样被调用的:

asyncFunc1()
 .then(asyncFunc2)
 .then(asyncFunc3)
 .then(asyncFunc4)
 .then(asyncFunc5);

这样,这些异步函数就会按照顺序一个一个依次执行了。

ES6中原生支持了Promise,不过在原生不支持Promise的环境中,我们有很多第三方库来支持,比如Q.js和Bluebird。它们一般都除了提供标准Promise的API外,还提供了一些标准之外但非常有用的API,使得异步流程的控制更加优雅。

从微信小程序的API文档中我们可以看到,框架提供的JavaScript API中很多函数其实都是异步的,如wx.setStorage(), wx.getStorage(), wx.getLocation()等等,它们也是提供的回调的处理方式,在参数中传入success, fail,complete回调函数,就可以对运行成功或失败进行分别处理。

如:

wx.getLocation({ 
 type: 'wgs84', 
 success: function(res) { 
  var latitude = res.latitude 
  var longitude = res.longitude 
  var speed = res.speed 
  var accuracy = res.accuracy 
 },
 fail: function() {
  console.error("get location failed")
 }
})

我们能不能让微信小程序的异步API支持Promise呢?答案是肯定的,我们当然可以一个一个的用Promise去包装这些API,但是这个还是比较麻烦的。不过,由于小程序的API的参数格式都比较统一,只接受一个object参数,回调都是在这个参数中设置,所以,这为我们的统一处理提供了便利,我们可以写一个非侵入性的工具方法,来完成这样的工作:

假设我们将这个工具方法写到一个名为的util.js的文件中:

var Promise = require('../libs/bluebird.min')  //我用了bluebird.js
function wxPromisify(fn) { 
 return function (obj = {}) {  
  return new Promise((resolve, reject) => {   
   obj.success = function (res) {    
    resolve(res)   
   }   

   obj.fail = function (res) {    
    reject(res)   
   }   

   fn(obj)  
  }) 
 }
}

module.exports = { 
 wxPromisify: wxPromisify
}

之后,我们来看一下如何使用这个方法,将原来回调方式的API变成Promise的方式:

var util = require('../utils/util')

var getLocationPromisified = util.wxPromisify(wx.getLocation)

getLocationPromisified({
 type: 'wgs84'
}).then(function (res) {
 var latitude = res.latitude 
 var longitude = res.longitude 
 var speed = res.speed 
 var accuracy = res.accuracy 
}).catch(function () {
 console.error("get location failed")
})

是不是很容易理解?

 以上就是关于使用Promise处理异步流程,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
理解JavaScript的caller,callee,call,apply
Apr 28 Javascript
关于div自适应高度/左右高度自适应一致的js代码
Mar 22 Javascript
jquery 元素控制(追加元素/追加内容)介绍及应用
Apr 21 Javascript
JavaScript实现url地址自动检测并添加URL链接示例代码
Nov 12 Javascript
angular.JS实现网页禁用调试、复制和剪切
Mar 31 Javascript
原生JS实现获取及修改CSS样式的方法
Sep 04 Javascript
深入浅析Vue.js 中的 v-for 列表渲染指令
Nov 19 Javascript
JS大坑之19位数的Number型精度丢失问题详解
Apr 22 Javascript
JQuery样式操作、click事件以及索引值-选项卡应用示例
May 14 jQuery
vue离开当前页面触发的函数代码
Sep 01 Javascript
vue中可编辑树状表格的实现代码
Oct 31 Javascript
一篇文章了解正则表达式的替换技巧
Feb 24 Javascript
史上最全JavaScript数组去重的十种方法(推荐)
Aug 17 #Javascript
AngularJS通过ng-Img-Crop实现头像截取的示例
Aug 17 #Javascript
Javascript中的getter和setter初识
Aug 17 #Javascript
简单实现js进度条加载效果
Mar 25 #Javascript
你可能不知道的JSON.stringify()详解
Aug 17 #Javascript
vue组件Prop传递数据的实现示例
Aug 17 #Javascript
js实现随机点名小功能
Aug 17 #Javascript
You might like
ThinkPHP快速入门实例教程之数据分页
2014/07/01 PHP
PHP中Notice错误常见解决方法
2017/04/28 PHP
phpStudy 2016 使用教程详解(支持PHP7)
2017/10/18 PHP
jQuery怎么解析Json字符串(Json格式/Json对象)
2013/08/09 Javascript
JS实现仿QQ聊天窗口抖动特效
2015/05/10 Javascript
js脚本分页代码分享(7种样式)
2015/08/19 Javascript
Winform客户端向web地址传参接收参数的方法
2016/05/17 Javascript
JS返回只包含数字类型的数组实例分析
2016/12/16 Javascript
Vue2.0 组件传值通讯的示例代码
2017/08/01 Javascript
Vue.js实现按钮的动态绑定效果及实现代码
2017/08/21 Javascript
微信小程序页面跳转功能之从列表的item项跳转到下一个页面的方法
2017/11/27 Javascript
详解在vue-cli中使用graphql即vue-apollo的用法
2018/09/08 Javascript
express express-session的使用小结
2018/12/12 Javascript
JavaScript设计模式之命令模式实例分析
2019/01/16 Javascript
Vue使用vue-recoure + http-proxy-middleware + vuex配合promise实现基本的跨域请求封装
2019/10/21 Javascript
VUE单页面切换动画代码(全网最好的切换效果)
2019/10/31 Javascript
[44:15]国士无双DOTA2 6.82版本详解(上)
2014/09/28 DOTA
[01:16:37]【全国守擂赛】第三周决赛 Dark Knight vs. 一个弱队
2020/05/04 DOTA
Python 实现链表实例代码
2017/04/07 Python
详解opencv Python特征检测及K-最近邻匹配
2019/01/21 Python
Django-rest-framework中过滤器的定制实例
2020/04/01 Python
Python requests HTTP验证登录实现流程
2020/11/05 Python
使用CSS3滤镜的filter:blur属性制作毛玻璃模糊效果的方法
2016/07/08 HTML / CSS
CSS3 中filter(滤镜)属性使用详解
2020/04/07 HTML / CSS
英国屋顶用品和材料超市:Roofing Supplies UK
2019/08/24 全球购物
Kickers鞋英国官网:男士、女士和儿童鞋
2021/03/08 全球购物
J2EE面试题集锦(附答案)
2013/08/16 面试题
设计部经理的岗位职责
2013/11/16 职场文书
资源环境与城市管理专业推荐信
2013/11/30 职场文书
学校七一活动方案
2014/01/19 职场文书
财务科科长岗位职责
2014/03/10 职场文书
初中英语课后反思
2014/04/25 职场文书
技能比武方案
2014/05/21 职场文书
淘宝客服工作职责
2014/07/11 职场文书
学生会生活部工作总结2015
2015/03/31 职场文书
《藏戏》教学反思
2016/02/23 职场文书