我的小程序全是对接的cms,为了方便栏目的调用,我都是先进行加载所有的栏目,然后存储到缓存里边,这样小程序的首页就可以直接通过该栏目缓存调用栏目或者子栏目信息,栏目属于不常更改的内容,提前缓存栏目算是一个好的办法。
但是实际应用中当中,小程序开发者工具api请求比较快,所以一般看不出什么问题,但是真机预览或者上线之后,用户的网速往往没有那么快,这就造成了首页加载完之后,可能这个请求栏目的api还没有返回结果,造成栏目报错,首页出现空白的情况。
这时候就需要考虑es6的新语法Promise了,简单来说,Promise的作用就是等待一个请求结束之后才会继续执行后边的程序。具体解释为:
Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。
Promise对象有以下两个特点。
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
应用到小程序中则为:
(1)首先 在app.js中创建一个Promise实例,如下:
get_cat(e) {
var that = this;
var CATEGORYS = swan.getStorageSync('categorys')
return new Promise(function (resolve, reject) {
if (CATEGORYS != '' || CATEGORYS.length != 0) {
resolve(CATEGORYS);//如果有栏目缓存直接调用
} else {//如果没有栏目缓存,请求API
swan.request({
url: that.globalData.api.category,
data: {
wxid: that.globalData.wxid
},
method: 'GET',
header: {
'content-type': 'application/json', // 默认值
'x-appsecret': that.globalData.appsecret
},
success: function (res) {
const categorys = res.data[0];
swan.setStorageSync('categorys', categorys)
resolve(categorys);//请求成功之后返回resolve
},
fail(e) {
reject();//请求失败之后返回reject
console.log('获取栏目缓存失败,请重试');
}
})
}
})
},
(2)在index.js中,如果某个方法必须要栏目请求之后调用,那么我们就可以
app.get_cat().then(function(){
that.get_newslist()//调用新闻方法
});
这样,get_newslist方法中如果用到了缓存,就会先等等栏目缓存加载完成之后再请求api,这样就不会报错,
此时又出现另外一个问题,就是,如果Promise对象确实请求时间比较长,那么会造成首页一直属于空白中,此时可以弄个加载页面,提示用户正在加载中,一旦get_newslist请求完成之后,隐藏该提示,正常显示文章即可!
<view hidden="{{loading1}}" class="loading">
<image src="../../images/loading.gif" mode='widthFix' style="width:120px; height:120px;"></image>
<view>小程序加载中...</view>
</view>