微信小程序中使用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 相关文章推荐
改版了网上的一个js操作userdata
Apr 27 Javascript
原生JS实现表单checkbook获取已选择的值
Jul 21 Javascript
jQuery实现单击按钮遮罩弹出对话框(仿天猫的删除对话框)
Apr 10 Javascript
浅析javascript中的DOM
Mar 01 Javascript
JavaScript使用cookie记录临时访客信息的方法
Apr 07 Javascript
jQuery中animate动画第二次点击事件没反应
May 07 Javascript
探析浏览器执行JavaScript脚本加载与代码执行顺序
Jan 12 Javascript
使用jquery实现的循环连续可停顿滚动实例
Nov 23 Javascript
微信小程序 生命周期和页面的生命周期详细介绍
Jan 19 Javascript
axios全局注册,设置token,以及全局设置url请求网段的方法
Sep 25 Javascript
微信小程序使用Vant Weapp组件库的方法步骤
Aug 01 Javascript
vue实现虚拟列表功能的代码
Jul 28 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
全国FM电台频率大全 - 24 贵州省
2020/03/11 无线电
基于empty函数的输出详解
2013/06/17 PHP
Laravel使用Caching缓存数据减轻数据库查询压力的方法
2016/03/15 PHP
PHP针对多用户实现更换头像功能
2016/09/04 PHP
PHP单例模式与工厂模式详解
2017/08/29 PHP
解决在laravel中auth建立时候遇到的问题
2019/10/15 PHP
node.js中的fs.chmod方法使用说明
2014/12/18 Javascript
JS JQUERY实现滚动条自动滚到底的方法
2015/01/09 Javascript
jQuery实现的类似淘宝网站搜索框样式代码分享
2015/08/24 Javascript
一个php+js实时显示时间问题
2015/10/12 Javascript
jquery实现多次上传同一张图片
2017/01/09 Javascript
JavaScript实现二分查找实例代码
2017/02/22 Javascript
浅谈JS对html标签的属性的干预以及对CSS样式表属性的干预
2017/06/25 Javascript
js微信分享实现代码
2020/10/11 Javascript
Django+vue跨域问题解决的详细步骤
2019/01/20 Javascript
vue的keep-alive用法技巧
2019/08/15 Javascript
node.JS路径解析之PATH模块使用方法详解
2020/02/06 Javascript
Vue用mixin合并重复代码的实现
2020/11/27 Vue.js
Python牛刀小试密码爆破
2011/02/03 Python
在Django的模型和公用函数中使用惰性翻译对象
2015/07/27 Python
pytorch 调整某一维度数据顺序的方法
2018/12/08 Python
Python测试模块doctest使用解析
2019/08/10 Python
python并发编程多进程 模拟抢票实现过程
2019/08/20 Python
python字符串,元组,列表,字典互转代码实例详解
2020/02/14 Python
python统计mysql数据量变化并调用接口告警的示例代码
2020/09/21 Python
通过代码实例了解Python3编程技巧
2020/10/13 Python
CSS3伪类选择器:nth-child()
2009/04/02 HTML / CSS
阿玛尼化妆品美国官网:Giorgio Armani Beauty
2017/02/02 全球购物
世界领先的豪华床上用品供应商之一:Bedeck Home
2019/03/18 全球购物
5个HTML5的常用本地存储方式详解与介绍
2021/03/27 HTML / CSS
腾讯广告词
2014/03/19 职场文书
2013年最新自荐信范文
2014/06/23 职场文书
最美孝心少年事迹材料
2014/08/15 职场文书
不同意离婚上诉状
2015/05/23 职场文书
2016国庆节67周年红领巾广播稿
2015/12/18 职场文书
Nginx代理同域名前后端分离项目的完整步骤
2021/03/31 Servers