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

微信小程序中使用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处理异步流程,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • 微信小程序 ES6Promise.all批量上传文件实现代码

    微信小程序 ES6Promise.all批量上传文件实现代码 客户端 Page({ onLoad: function() { wx.chooseImage({ count: 9, success: function({ tempFilePaths }) { var promise = Promise.all(tempFilePaths.map((tempFilePath, index) => { return new Promise(function(resolve, reject) { wx.

  • 让微信小程序支持ES6中Promise特性的方法详解

    遇到的问题 微信开发者工具更新版本后, 移除了开发者工具对 ES6 中 Promise 特性原生的支持, 理由是因为实体机器是不支持 Promise 的, 所以我们需要引入第三方的 Promise 库 微信更新日志 解决方案 下载第三方库 在这里我引入的是 Bluebird 库, 可以到Bluebird官网 下载需要的文件,也可以通过本地下载 Bluebrid 提供了两种已经构建好的完整的 Promise 库文件, 未经压缩的 bluebird.js 和已压缩的 bluebird.min.js

  • 微信小程序 引入es6 promise

    微信小程序开发两个月了.大家的项目都在不断迭代.已经不是小程序.这时候就会遇到多层回调嵌套的问题.有些目不忍视了.迫不得已引入es6-promise.在微信小程序内测的时候promise不需要手动引入,后来被微信移除了.看看效果. promise详细的介绍我就不说了.有很多大神写过. 看看目录,引入es6-promise就可以用了. 目录 1.网络请求 wxRequest.js 这里只写了get和post. 我经常会在网络请求的时候用微信原生showToast(),所以最后加了finally,方

  • 微信小程序 es6-promise.js封装请求与处理异步进程

    微信小程序 es6-promise.js封装请求与处理异步进程 下载es6-promise.js置于根目录下的libs文件夹下: 在根目录utils文件夹下新建httpsPromisify.js,即定义封装请求的方法 var Promise = require('../libs/es6-promise.min') function httpsPromisify(fn) { return function (obj = {}) { return new Promise((resolve, reje

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

    微信小程序中使用Promise进行异步流程处理的实例详解 我们知道,JavaScript是单进程执行的,同步操作会对程序的执行进行阻塞处理.比如在浏览器页面程序中,如果一段同步的代码需要执行很长时间(比如一个很大的循环操作),则页面会产生卡死的现象. 所以,在JavaScript中,提供了一些异步特性,为程序提供了性能和体验上的益处,比如可以将代码放到setTimeout()中执行:或者在网页中,我们使用Ajax的方式向服务器端做异步数据请求.这些异步的代码不会阻塞当前的界面主进程,界面还是可以

  • 微信小程序中form 表单提交和取值实例详解

    微信小程序中form 表单提交和取值实例详解 我们知道,如果我们直接给 input 添加 bindinput,比如:<input bindinput="onUsernameInput" />,那么可以在 onUsernameInput 中直接使用 e.detail.value,即: onUsernameInput : function(e) { e.detail.value; } 但是,如果有多个输入控件,我们不可能为每个控件添加 bindinput.bindchange

  • 微信小程序开发数据缓存基础知识辨析及运用实例详解

    提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容. 提示:以下是本篇文章正文内容,下面案例可供参考 一.微信数据缓存是什么? 在实际开发中,在用到一个数据时,我们需要调用api接口去得到,然后渲染在页面中,但是对于一些数据,是经常需要使用的,如果每次使用时都需要调用api接口,会十分麻烦.数据缓存就解决了这个问题,我们可以在初次调用某api得到数据的同时将数据缓存,那么在之后的使用过程

  • 微信小程序 增、删、改、查操作实例详解

    微信小程序 增.删.改.查操作实例详解 1.以收货地址的增删改查为例 2.文件目录 js文件是逻辑控制,主要是它发送请求和接收数据, json 用于此页面局部 配置并且覆盖全局app.json配置, wxss用于页面的样式设置, wxml就是页面,相当于html <form bindsubmit="addSubmit"> <view class="consignee"> <text class="consignee-tit&q

  • 微信小程序 点击控件后选中其它反选实例详解

    微信小程序 点击控件后选中其它反选实例详解 前言: 如果需要实现进来进行给按钮加上买一送一的样式,或者单击就选中单个按钮,只能靠css结合js进行控制了,小程序暂时没有这样的控件. 实现效果图: 微信小程序进来的时候自动进行按钮样式的初始化,这个需要一个字段做判断,加上正则表达式wxml文件: <block wx:for="{{liuliangItems}}"> <block wx:if="{{item.one2one == 1}}"> &l

  • 微信小程序中换行空格(多个空格)写法详解

    在小程序中HTML的网页实体无法正常使用,小程序中的写法为:  一.空格,换行 <text>你好!\t七月流火啊!\n我在下一行</text> \t 空格( 多个只会显示一个空格) \n 换行 二.连续空格 <view> <text space="ensp">你好 啊 哈哈哈(空格是中文字符一半大小)</text> </view> <view> <text space="emsp&quo

  • 微信小程序 图片加载(本地,网路)实例详解

    在微信小程序中,要显示一张图片,有两种图片加载方式: 加载本地图片 加载网络图片 加载本地图片 <image class="widget__arrow" src="/image/arrowright.png" mode="aspectFill"> </image> src="/image/arrowright.png" 这句就是加载本地图片资源的.想想iOS中的加载本地图片,imageName:,类似.

  • 微信小程序 选择器(时间,日期,地区)实例详解

    微信小程序 选择器(时间,日期,地区) 微信小程序 开发由于本人最近学习微信小程序的开发,根据自己的实践结果整理了下结果,对日期选择器,时间选择器,地区选择器做的实例,有不对的地方,希望大家指正. 用微信封装好的控件感觉很好,为我们开发人员省去了很多麻烦.弊端就是不能做大量的自定义.今天试用了选择器. 上gif: 上代码: 1.index.js //index.js //获取应用实例 var app = getApp() Page({ data: { date: '2016-11-08', ti

  • uni-app微信小程序登录并使用vuex存储登录状态的思路详解

    微信小程序注册登录思路 (这是根据自身的项目的思路,不一定每个项目都适用) 1.制作授权登录框,引导用户点击按钮 2.uni.login获取code 3.把code传给后端接口,后端返回如下数据 openid: "ogtVM5RWdfadfasdfadfadV5s" status: 1 // 状态码:status==0(该用户未注册,需调用注册接口) status==1(该用户已注册) 4.判断用户是否注册,并调用用户信息接口 (1)若已注册则提示登录成功,并调用后台给的获取用户信息的

  • 微信小程序事件绑定传参冒泡及捕获的示例详解

    目录 常见的事件有: currentTarget和target的区别 事件传递参数 touches和changedTouches的区别 事件的绑定两种方法 事件传参 事件的冒泡与事件的捕获 小结 常见的事件有: 类型 触发条件 最低版本 touchstart 手指触摸动作开始   touchmove 手指触摸后移动   touchcancel 手指触摸动作被打断,如来电提醒,弹窗   touchend 手指触摸动作结束   tap 手指触摸后马上离开   longpress 手指触摸后,超过35

随机推荐