大多数人应该都会碰到以下场景:
代码大概是这样:
app.js:
/*小程序加载时异步获取token*/
onLaunch: function () {
wx.request({
url: 'https://test.com/onLogin',
data: json,
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded',
},
success : function(res) {
//把token放入本地缓存
wx.setStorageSync('cookie', res.header['Set-Cookie'])
}
})
}
index.js:
/*首页需要token获取服务器数据*/
onShow:function(){
wx.request({
url: 'https://test.com/getData',
data: json,
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded',
'Cookie': wx.getStorageSync('cookie')
},
success : function(res) {
//更新首页数据
this.setData({
data:res.data
})
}
})
}
index.wxml:
<view>{{data}}<view>
结果发现第一次进入首页没有数据(data是空的);再次进入首页时就有了,很多新手同学百思不得其解
这实际上是因为wx.request是异步请求,在请求结果(也就是token)没返回前,首页就已经发起了数据请求,实际情况如下图:
那我们要如何才能保证首页在获取token之后再打开呢?
一般的做法是把后续操作放在登录后的回调函数里,这样也能解决同步加载的问题。但这样代码就得全写到一块,加深了代码的耦合,而且很可能还会形成回调地狱,十分不美观。
就像下面这样:
onLaunch: function () {
wx.login({
success: res => {
wx.request({
url: 'https://test.com/onLogin',
data: json,
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded',
},
success : function(res) {
wx.request({
url: 'https://test.com/getData',
data: json,
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded',
'Cookie': res.header['Set-Cookie']
},
success : function(res) {
//更新首页数据
this.setData({
data:res.data
})
}
})
}
})
}
})
}
下面我们看看用promise是怎么处理这个问题的。
网上已经有很多promise的介绍和教程,这里不再缕述,直接上代码:
app.js:
//全局变量,存放登录结果
globalData:{
login:null
},
/*小程序加载时异步获取token*/
onLaunch: function () {
var login = new Promise((resolve, reject) => {
wx.request({
url: 'https://test.com/onLogin',
data: json,
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded',
},
success : function(res) {
//把token放入本地缓存
wx.setStorageSync('cookie', res.header['Set-Cookie'])
resolve(res)
}
})
})
}
//把promise封装的登陆结果放入全局变量中
this.globalData.login = login
index.js:
/*首页需要token获取服务器数据*/
onShow:function(){
getApp().globalData.login.then(()=>{
wx.request({
url: 'https://test.com/getData',
data: json,
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded',
'Cookie': wx.getStorageSync('cookie')
},
success : function(res) {
//更新首页数据
this.setData({
data:res.data
})
}
})
})
}
上面的代码通过promise,将异步请求的结果后处理分离了出来,实现了代码的解藕
后续所有需要登录后的操作,都可以在任意地方使用login.then(),十分方便。
总结
个人认为promise实际上就是给这一个方法增加了两个后处理接口:resolve()和reject()。其中reject()还承包了异常的后处理。然后再通过then和catch去实现这两个后处理。这样就可以把一些长逻辑的代码段拆分出来,在各自的模块进行处理。