我的小程序全是對接的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>