原文連接: https://www.xksblog.top/talk-...
見到wx.request
的第一眼,就讓我想起了$.ajax
這東西,使用起來確實有不少不方便,不能忍,幸虧小程序是支持ES6語法的,因此可使用promise稍加改造。html
先來講說wx.request爲何不能忍。ajax
Page({ data: { myData: '' }, // loadMyData函數用於打印myData的值 loadMyData () { console.log('獲取到的數據爲:' + this.data.myData) }, // 生命週期函數onload用於監聽頁面加載 onload: function () { wx.request({ url: 'https://api', // 某個api接口地址 success: res => { console.log(res.data) this.setData({ myData: res.data }) console.log(this.data.myData) } }) // 調用以前的函數 this.loadMyData() } })
而後咱們會在控制檯到這樣的結果:json
這實際上是一個很簡單的異步問題,wx.request是異步請求,JS不會等待wx.request執行完畢再往下執行,因此JS按順序會先執行this.loadMyData(),等服務器返回數據之後,loadMyData()早就執行完了,固然也就沒有拿到值啦。小程序
其實咱們在同步流程中才說「返回」,異步沒有「返回」這個概念(或者說異步返回是沒有意義的),異步對應的是「回調」,也就是說,對於一個異步函數,咱們應該傳入一個「回調函數」來接收結果。微信小程序
最簡單的解決方案,就是把須要使用異步數據的函數寫在回調裏:api
... onload: function () { wx.request({ url: 'https://api', // 某個api接口地址 success: res => { console.log(res.data) this.setData({ myData: res.data }) console.log(this.data.myData) // 把使用數據的函數寫在回調函數success中 this.loadMyData() } }) }
這樣就能夠正確輸出了:promise
可是若是邏輯複雜,須要多層異步操做,會出現怎麼樣的狀況呢?服務器
asyncFn1(function(){ //... asyncFn2(function(){ //... asyncFn3(function(){ //... asyncFn4(function(){ //... asyncFn5(function(){ //... }); }); }); }); });
有沒有感受頭皮發麻?什麼優雅什麼可讀性,瞬間蕩然無存,這就是恐怖的「回調地獄」(Callback Hell)。微信
而咱們發現,微信小程序的網絡請求wx.request,也正是這種依靠回調函數的形式,相似於之前的$.ajax
,它在邏輯複雜、頁面執行順序要求多的狀況下,弊端也是很明顯的。不過好在小程序支持ES6,咱們能夠盡情地擁抱Promise!網絡
Promise這東西簡單說來就是,它能夠將異步的執行邏輯和結果處理分離,摒棄了一層又一層的回調嵌套,使得處理邏輯更加清晰。想具體瞭解的還請自行查找資料。
如今咱們就用Promise包裝一下wx.request:
/** * requestPromise用於將wx.request改寫成Promise方式 * @param:{string} myUrl 接口地址 * @return: Promise實例對象 */ const requestPromise = myUrl => { // 返回一個Promise實例對象 return new Promise((resolve, reject) => { wx.request({ url: myUrl, success: res => resolve(res) }) }) } // 我把這個函數放在了utils.js中,這樣在須要時能夠直接引入 module.exports = requestPromise
如今再使用試試:
// 引用模塊 const utilApi = require('../../utils/util.js') Page({ ... // 生命週期函數onload用於監聽頁面加載 onLoad: function () { utilApi.requestPromise("https://www.bilibili.com/index/ding.json") // 使用.then處理結果 .then(res => { console.log(res.data) this.setData({ myData: res.data }) console.log(this.data.myData) this.loadMyData() }) } })
結果和使用回調函數一致。當有多個異步請求時,直接不斷地.then(fn)去處理便可,邏輯清晰。
固然,這裏只是寫了一個最簡單的Promise函數,還不完整。更完整的Promise化wx.request,等之後業務須要再完善吧。另外各類小程序開發框架也都有了現成的promise化API,拿來即用。