本文详解如何在微信小程序JS中使用Promise优化异步函数处理。通过对比传统回调地狱,展示如何引入es6-promise组件,封装getUserInfo及网络请求等常用方法至utils.js,并利用then链式调用实现简洁易读的代码结构,提升小程序开发效率。
引言:Promise优化异步处理的必要性
在传统JavaScript开发中,开发者通常依赖回调函数处理逻辑。然而,随着回调层级的增加和异步复杂性的提升,代码可读性急剧下降。为解决这一问题,引入Promise机制成为优化JS函数处理的有效手段。它不仅能显著改善异步回调的可读性,还能使调用代码更加简洁。本文将具体介绍如何在微信小程序的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的回调函数来执行后续逻辑。为确保安全性,调用前还需额外判断cb类型是否为函数(typeof cb == "function")。尽管这种处理方式相对直观易懂,但在复杂场景下仍存在局限。
然而,当代码中包含大量异步操作,且必须保证这些操作按特定顺序执行时,传统回调方式会导致代码结构混乱,可读性极差。例如出现以下极端嵌套情况:
asyncFunc1(function(){
//...
asyncFunc2(function(){
//...
asyncFunc3(function(){
//...
asyncFunc4(function(){
//...
asyncFunc5(function(){
//...
});
});
});
});
});
若改用Promise机制,仅需对原有逻辑进行简单包装即可解决上述问题。
function asyncFunc1(){
return new Promise(function (resolve, reject) {
//...
})
}
Promise在小程序中的引入与配置
2、Promise的使用介绍
Promise的使用相对简便,初学者可参考阮一峰编写的Promise入门教程。若要在JS函数中引入Promise,需先包含对应的JavaScript组件。
开发者可在GitHub上下载es6-promise组件JS文件,并将其引入小程序项目中。
为便于管理,可在项目中创建一个辅助类文件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的代码封装与复用实践
引入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机制能使代码结构更加简洁且易于阅读。
以上即为本文的全部内容,希望对各位的学习有所帮助,也欢迎大家继续支持本站。