问题概述
基于小程序request请求是异步的特性,app.js onLaunch()
中的请求与index.js onLoad()
中的请求是同时进行的,导致onLoad()
中如果有基于onLaunch()
返回的数据的请求,会有报错,这样会使onLoad()
中request请求的数据“第一次”无法正常获取。
我的小程序中所有的requset请求都需要在header中带着用户唯一的token进行发起,而token是在app.js onLaunch()
中的wx.login()返回中获取到的(由code到后台换取),之后通过wx.setStorageSync('token', res.data)
存到小程序中。要解决问题,就需要解决request请求异步的问题,而且是在两个js文件之间。
使用Promise()
稍微说一下promise
var promise = new Promise(function(resolve, reject) {
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then(function(value) {
// success
}, function(value) {
// failure
});
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 方法和 reject 方法。
- 如果异步操作成功,则用 resolve 方法将 Promise 对象的状态,从「未完成」变为「成功」(即从 pending 变为 resolved);
- 如果异步操作失败,则用 reject 方法将 Promise 对象的状态,从「未完成」变为「失败」(即从 pending 变为 rejected)。
接下来在小程序中引入promise库。到bluebird官网中下载压缩版本的promise库。直接打开bluebird.core.min.js
,复制代码。
Bluebird is a fully featured JavaScript promises library with unmatched performance.
小程序内新建一个promise.js文件,将bluebird.core.min.js
中的代码复制进去。
在app.js
中通过require
引入:
<!-- app.js -->
const Promise = require('units/promise.js');
这样就可以在小程序内使用promise了,该库大小大概在64kb左右,可以接受。
接下来直接贴代码:
<!-- app.js -->
App({
onLaunch: function(){
<!-- 调整代码结构,原本在此进行的wx.login操作放到下面去 -->
...
},
//登录,获取token
getToken: function(){
let _this = this;
return new Promise(function(resolve, reject){
wx.checkSession({
success: function (res) { resolve(res); },
fail: function (res) {
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
if (res.code) {
wx.request({
url: CONFIG.loginUrl,
data: {
code: res.code
},
header: {
'shopId': CONFIG.shopId
},
method: 'POST',
success: res => {
wx.setStorageSync('token', res.data); //储存返回的token
resolve(res);
}
})
} else {
console.log('获取用户登录态失败!' + res.errMsg);
reject('error');
}
}
})
}
})
})
}
})
接下来在index.js中处理
const app = getApp();
Page({
onLoad: function(){
let token = wx.getStorageSync('token');
if (token == ''){
//第一次登录,获取登录状态
app.getToken().then(function (res) {
_this.getData(); //此时token必然已经获取到,且getData()在此时才会执行
})
}else{
//有token的情况直接获取数据
_this.getData();
}
},
//获取数据
getData: function(){
wx.request({
header: {
'token': wx.getStorageSync('token')
},
url: 'https://xxxxx.xxxxx',
method: 'GET',
success: res => {
console.log(res);
}
})
}
})
这时候清除一下开发工具的缓存,再次编译页面,打开调试面板的network,可以看到index.js
中的wx.request
请求是在wx.login()
的success后才开始的,这样就达到了我们的目的,问题解决。