详解在微信小程序的JS脚本中使用Promise来优化函数处理


Posted in Javascript onMarch 06, 2019

在我们传统的Javascript开发函数编写中,我们习惯了回调函数的处理,不过随着回调函数的增多,以及异步处理的复杂性等原因,代码越来越难读,因此诞生了使用Promise来优化JS函数处理的需求,引入Promise确实能够很好的解决异步回调函数的可读性等问题,同时也使得我们调用的时候代码简洁一些,本文介绍如何在小程序的JS代码里面使用Promise来封装一些函数的做法。

1、小程序传统的回调处理

例如我们生成一个小程序,里面的app.js里面就自动带有一个getUserInfo的函数,这个是使用传统模式的回调函数。

//app.js
App({
 onLaunch: function () {
 //调用API从本地缓存中获取数据
 var logs = wx.getStorageSync('logs') || []
 logs.unshift(Date.now())
 wx.setStorageSync('logs', logs)
 },
 
 getUserInfo:function(cb){
 var that = this
 if(this.globalData.userInfo){
  typeof cb == "function" && cb(this.globalData.userInfo)
 }else{
  //调用登录接口
  wx.login({
  success: function () {
   wx.getUserInfo({
   success: function (res) {
    that.globalData.userInfo = res.userInfo
    typeof cb == "function" && cb(that.globalData.userInfo)
   }
   })
  }
  })
 }
 },
 globalData:{
 userInfo: null,
 openid: null
 }
})

这种是通过 传入一个cb的回调函数进行处理,使用的时候为了安全性,还需要进一步判断其类型是否为函数:typeof cb == "function",这种处理还是相对比较易懂。

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

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

如果我们改用Promise来处理,那么进行一层简单的包装即可。

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

2、Promise的使用介绍

Promise的使用相对比较简单,我们入门可以参考下相关介绍:阮一峰 promise入门,如果我们在JS函数里面引入它的话,那么需要包含对应的javascript组件

我们可以在Github上下载对应的组件JS,引入小程序项目即可:es6-promise

我们为了方便,在项目中创建一个辅助类utils.js,然后在其中引入Promise的脚本,如下所示。

const Promise = require('./Promise')

然后在APP.js里面,我们修改原来的getUserInfo函数如下 

//app.js
const utils = require('./utils/util.js')

App({
 onLaunch: function() {
  //调用API从本地缓存中获取数据
  var logs = wx.getStorageSync('logs') || []
  logs.unshift(Date.now())
  wx.setStorageSync('logs', logs)
 },

 getUserInfo() {
  return new utils.Promise((resolve, reject) => {
   if (this.globalData.userInfo) {
    resolve(this.globalData.userInfo)
   }
   return utils.getUserInfo().then(res => {
    resolve(this.globalData.userInfo = res.userInfo)
   })
  })
 },

 //获取系统信息
 getSystemInfo() {
  return new utils.Promise((resolve, reject) => {
   var that = this
   if (that.globalData.systemInfo) {
    resolve(that.globalData.systemInfo)
   } else {
    wx.getSystemInfo({
     success: function(res) {
      resolve(that.globalData.systemInfo = res);
     }
    })
   }
  })
 },
 //全局对象
 globalData: {
  userInfo: null,
  systemInfo: null
 },
 utils
})

我们看到,所有原先的函数,我们如果需要引入Promise处理的话,增加一层的函数体即可。

return new utils.Promise((resolve, reject) => {
  
  // 原来的函数体代码 
});

这样我们调用的时候,使用then函数进行处理即可,类似下面的代码。

getUserInfo().then(user => this.setData({userInfo:user})).catch(console.log);

引入这个Promise后,我们为了进一步实现代码的重用,可以把一些常见的函数放到utils.js来,这样可以实现代码的重用。

//用户登录
function login(){
 return new Promise((resolve,reject) => wx.login({
 success:resolve,
 fail:reject
 }))
}

//获取用户信息
function getUserInfo(){
 return login().then(res => new Promise((resolve,reject) => 
 wx.getUserInfo({
  success:resolve,
  fail:reject
 })
 ))
}
function requstGet(url,data){
 return requst(url,'GET',data)
}

function requstPost(url,data){
 return requst(url,'POST',data)
}

//封装Request请求方法
function requst(url,method,data = {}){
 wx.showNavigationBarLoading()
 data.method = method
 return new Promise((resove,reject) => {
 wx.request({
  url: url,
  data: data,
  header: {},
  method: method.toUpperCase(), // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
  success: function(res){
  wx.hideNavigationBarLoading()
  resove(res.data)
  },
  fail: function(msg) {
  console.log('reqest error',msg)
  wx.hideNavigationBarLoading()
  reject('fail')
  }
 })
 })
}

然后发布对应的接口,以供其他模块使用即可。 

//发布的接口
module.exports = {
 Promise,makeArray,getUserInfo,
 get:requstGet,post:requstPost,requst,decodeHtml,

 formatTime,getDateDiff
}

封装好这些公用方法后,我们在页面里面进行调用即可,调用的代码如下所示(演示代码从地址里面获取数据,并绑定到界面上)

//使用Comprise的封装函数展现
  var url ='http://localhost:27206/api/Framework/Information/FindByCode';
  var companyurl = "http://www.iqidi.com";
  var json = {code: 'company'};
  app.utils.get(url, json).then(function(res) { 
  var data = { url: companyurl, image: res.Picture, content: res.Content };
  that.setData({
   item : data
  });
  WxParse.wxParse('content', 'html', data.content, that, 25);
  });

而如果我们使用原来的函数,那么实现代码如下所示。

// 使用标准的wx.request函数实现展现
  var url ='http://localhost:27206/api/Framework/Information/FindByCode';
  var companyurl = "http://www.iqidi.com";
  var json = {code: 'company'};
  wx.request({
   url: url,
   data: json,
   success: function(res) {
   console.log(res);
   var data = { url: companyurl, image: res.data.Picture, content: res.data.Content };
   that.setData({
    item : data
   });
   WxParse.wxParse('content', 'html', data.content, that, 25);
   }
  })

如果对于复杂流程的函数处理,使用Promise来处理,会显得更加简洁易读。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
asp(javascript)全角半角转换代码 dbc2sbc
Aug 06 Javascript
jquery无缝向上滚动实现代码
Mar 29 Javascript
JS实现遮罩层效果的简单实例
Nov 12 Javascript
jQuery实现DIV层淡入淡出拖动特效的方法
Feb 13 Javascript
JS操作XML实例总结(加载与解析XML文件、字符串)
Dec 08 Javascript
vue component组件使用方法详解
Jul 14 Javascript
浅谈函数调用的不同方式,以及this的指向
Sep 17 Javascript
JavaScript插件Tab选项卡效果
Nov 14 Javascript
微信小程序tabBar用法实例详解
Dec 04 Javascript
vue自定义指令directive的使用方法
Apr 07 Javascript
el-select数据过多懒加载的解决(loadmore)
May 29 Javascript
详解Howler.js Web音频播放终极解决方案
Aug 23 Javascript
移动端(微信等使用vConsole调试console的方法
Mar 05 #Javascript
利用Vconsole和Fillder进行移动端抓包调试方法
Mar 05 #Javascript
深入理解Puppeteer的入门教程和实践
Mar 05 #Javascript
[jQuery] 事件和动画详解
Mar 05 #jQuery
Vue 事件处理操作实例详解
Mar 05 #Javascript
Vue插槽原理与用法详解
Mar 05 #Javascript
JavaScript基于遍历操作实现对象深拷贝功能示例
Mar 05 #Javascript
You might like
微信开发之网页授权获取用户信息(二)
2016/01/08 PHP
PHP中的使用curl发送请求(GET请求和POST请求)
2017/02/08 PHP
详细对比php中类继承和接口继承
2018/10/11 PHP
PHP+redis实现微博的拉模型案例详解
2019/07/10 PHP
JavaScript 入门·JavaScript 具有全范围的运算符
2007/10/01 Javascript
JavaScript设置FieldSet展开与收缩
2009/05/15 Javascript
关于jquery append() html时的小问题的解决方法
2010/12/16 Javascript
JavaScript实现拼音排序的方法
2012/11/20 Javascript
兼容所有浏览器的js复制插件Zero使用介绍
2014/03/19 Javascript
JavaScript关闭当前页面(窗口)不带任何提示
2014/03/26 Javascript
javascript实现控制浏览器全屏
2015/03/30 Javascript
深入浅析knockout源码分析之订阅
2016/07/12 Javascript
vuejs事件中心管理组件间的通信详解
2017/08/09 Javascript
JS实现前端页面的搜索功能
2018/06/12 Javascript
JavaScript使用类似break机制中断forEach循环的方法
2018/11/13 Javascript
详解vue 路由跳转四种方式 (带参数)
2019/04/28 Javascript
node+vue实现文件上传功能
2020/05/28 Javascript
vue项目接口域名动态获取操作
2020/08/13 Javascript
[02:30]DOTA2放量测试专访海涛:呼吁保护新手玩家
2013/08/26 DOTA
使用python将mdb数据库文件导入postgresql数据库示例
2014/02/17 Python
Python合并多个装饰器小技巧
2015/04/28 Python
Swift中的协议(protocol)学习教程
2016/07/08 Python
python 分离文件名和路径以及分离文件名和后缀的方法
2018/10/21 Python
Django 接收Post请求数据,并保存到数据库的实现方法
2019/07/12 Python
python字符串分割及字符串的一些常规方法
2019/07/24 Python
python 有效的括号的实现代码示例
2019/11/11 Python
Python 基于FIR实现Hilbert滤波器求信号包络详解
2020/02/26 Python
移动端解决悬浮层(悬浮header、footer)会遮挡住内容的3种方法
2015/03/27 HTML / CSS
Clarisonic美国官网:科莱丽声波洁面仪
2017/10/12 全球购物
德国高品质男装及配饰商城:Cultizm(Raw Denim原色牛仔裤)
2018/04/16 全球购物
应用服务器有那些
2012/01/19 面试题
导游个人求职信
2014/04/25 职场文书
十佳标兵事迹材料
2014/08/18 职场文书
工商局所长四风自我剖析及整改措施
2014/10/26 职场文书
超市督导岗位职责
2015/04/10 职场文书
Redis实现订单过期删除的方法步骤
2022/06/05 Redis