微信小程序中使用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 相关文章推荐
点击显示指定元素隐藏其他同辈元素的方法
Feb 19 Javascript
jquery.form.js用法之清空form的方法
Mar 07 Javascript
JavaScript将XML转成JSON的方法
Mar 12 Javascript
自定义刻度jQuery进度条及插件
Sep 02 Javascript
Bootstrap Fileinput文件上传组件用法详解
May 10 Javascript
JavaScript字符集编码与解码详谈
Feb 02 Javascript
微信小程序 下拉菜单的实现
Apr 06 Javascript
Bootstrap 表单验证formValidation 实现表单动态验证功能
May 17 Javascript
node.js 模块和其下载资源的镜像设置的方法
Sep 06 Javascript
Vue组件之高德地图地址选择功能的实例代码
Jun 21 Javascript
Vue3.0的优化总结
Oct 16 Javascript
element-ui点击查看大图的方法示例
Dec 14 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
php中截取中文字符串的代码小结
2011/07/17 PHP
PHP 解决session死锁的方法
2013/06/20 PHP
php使用curl和正则表达式抓取网页数据示例
2014/04/13 PHP
phpStudy2016 配置多个域名期间遇到的问题小结
2017/10/19 PHP
IE下使用cloneNode注意事项分享
2012/11/22 Javascript
JavaScript中判断原生函数检查function是否是原生代码
2014/09/09 Javascript
js使用onmousemove和onmouseout获取鼠标坐标的方法
2015/03/31 Javascript
jquery ajaxfileupload异步上传插件使用详解
2017/02/08 Javascript
js中数组插入、删除元素操作的方法
2017/02/15 Javascript
JS实现获取进今年第几天是周几的方法分析
2018/06/27 Javascript
vue实现城市列表选择功能
2018/07/16 Javascript
对angularJs中controller控制器scope父子集作用域的实例讲解
2018/10/08 Javascript
详解babel升级到7.X采坑总结
2019/05/12 Javascript
vue中的mescroll搜索运用及各种填坑处理
2019/10/30 Javascript
jQuery事件模型默认行为执行顺序及trigger()与 triggerHandler()比较实例分析
2020/04/30 jQuery
微信小程序学习总结(一)项目创建与目录结构分析
2020/06/04 Javascript
[14:56]教你分分钟做大人:巫医
2014/10/30 DOTA
python多进程操作实例
2014/11/21 Python
python2 与 python3 实现共存的方法
2018/07/12 Python
dataframe 按条件替换某一列中的值方法
2019/01/29 Python
django 微信网页授权认证api的步骤详解
2019/07/30 Python
Python列表解析操作实例总结
2020/02/26 Python
在 Python 中使用 MQTT的方法
2020/08/18 Python
宝塔面板出现“open_basedir restriction in effect. ”的解决方法
2021/03/14 PHP
Html5在手机端调用相机的方法实现
2020/05/13 HTML / CSS
ASOS英国官网:英国在线时装和化妆品零售商
2017/05/19 全球购物
师范应届生求职信
2013/11/15 职场文书
机械制造专业个人的自我评价
2013/12/28 职场文书
热爱祖国演讲稿
2014/05/04 职场文书
护理专业毕业生自荐书
2014/05/24 职场文书
法人授权委托书范本
2014/09/17 职场文书
学法用法心得体会(2016推荐篇)
2016/01/21 职场文书
高质量“欢迎词”
2019/04/03 职场文书
python flask开发的简单基金查询工具
2021/06/02 Python
人民币符号
2022/02/17 杂记
mysql性能优化以及配置连接参数设置
2022/05/06 MySQL