注冊登錄

微信小程序wx.request異步解決方案

2020-09-28
導(dǎo)讀:見到 wx.request 的第一眼,就讓我想起了 $.ajax 這東西,使用起來確實(shí)有很多不方便,不能忍,幸好小程序是支持ES6語法的,所以可以使用promise稍加改造。 先來說說wx.request為什么不能忍...

見到wx.request的第一眼,就讓我想起了$.ajax這東西,使用起來確實(shí)有很多不方便,不能忍,幸好小程序是支持ES6語法的,所以可以使用promise稍加改造。

先來說說wx.request為什么不能忍。

鋪墊:“看得見卻抓不住“的異步請求

微信小程序wx.request異步解決方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Page({
  data: {
    myData: ''
  },
  // loadMyData函數(shù)用于打印myData的值
  loadMyData () {
    console.log('獲取到的數(shù)據(jù)為:' + this.data.myData)
  },
  // 生命周期函數(shù)onload用于監(jiān)聽頁面加載
  onload: function () {
    wx.request({
      url: 'https://api',  // 某個api接口地址
      success: res => {
        console.log(res.data)
        this.setData({
          myData: res.data
        })
        console.log(this.data.myData)
      }
    })
    // 調(diào)用之前的函數(shù)
    this.loadMyData()
  }
})

這其實(shí)是一個很簡單的異步問題,wx.request是異步請求,JS不會等待wx.request執(zhí)行完畢再往下執(zhí)行,所以JS按順序會先執(zhí)行this.loadMyData(),等服務(wù)器返回數(shù)據(jù)以后,loadMyData()早就執(zhí)行完了,當(dāng)然也就沒有拿到值啦。

其實(shí)我們在同步流程中才說“返回”,異步?jīng)]有“返回”這個概念(或者說異步返回是沒有意義的),異步對應(yīng)的是“回調(diào)”,也就是說,對于一個異步函數(shù),我們應(yīng)該傳入一個“回調(diào)函數(shù)”來接收結(jié)果。

初步解決:通過回調(diào)接收結(jié)果

最簡單的解決方案,就是把需要使用異步數(shù)據(jù)的函數(shù)寫在回調(diào)里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
onload: function () {
  wx.request({
    url: 'https://api',  // 某個api接口地址
    success: res => {
      console.log(res.data)
      this.setData({
        myData: res.data
      })
      console.log(this.data.myData)
      // 把使用數(shù)據(jù)的函數(shù)寫在回調(diào)函數(shù)success中
      this.loadMyData()
    }
  })
}

這樣就可以正確輸出了:

 

但是如果邏輯復(fù)雜,需要多層異步操作,會出現(xiàn)怎么樣的情況呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
asyncFn1(function(){
  //...
  asyncFn2(function(){
    //...
    asyncFn3(function(){
      //...
      asyncFn4(function(){
        //...
        asyncFn5(function(){
           //...
        });
      });
    });
  });
});

有沒有感覺頭皮發(fā)麻?什么優(yōu)雅什么可讀性,瞬間蕩然無存,這就是恐怖的“回調(diào)地獄”(Callback Hell)。

而我們發(fā)現(xiàn),微信小程序的網(wǎng)絡(luò)請求wx.request,也正是這種依靠回調(diào)函數(shù)的形式,類似于以前的$.ajax,它在邏輯復(fù)雜、頁面執(zhí)行順序要求多的情況下,弊端也是很明顯的。不過好在小程序支持ES6,我們可以盡情地?fù)肀romise!

使用Promise包裝wx.request

Promise這東西簡單說來就是,它可以將異步的執(zhí)行邏輯和結(jié)果處理分離,摒棄了一層又一層的回調(diào)嵌套,使得處理邏輯更加清晰。想具體了解的還請自行查找資料。

現(xiàn)在我們就用Promise包裝一下wx.request:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * requestPromise用于將wx.request改寫成Promise方式
 * @param:{string} myUrl 接口地址
 * @return: Promise實(shí)例對象
 */
const requestPromise = myUrl => {
  // 返回一個Promise實(shí)例對象
  return new Promise((resolve, reject) => {
    wx.request({
      url: myUrl,
      success: res => resolve(res)
    })
  })
}
// 我把這個函數(shù)放在了utils.js中,這樣在需要時可以直接引入
module.exports = requestPromise

 

現(xiàn)在再使用試試:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 引用模塊
const utilApi = require('../../utils/util.js')
Page({
  ...
  // 生命周期函數(shù)onload用于監(jiān)聽頁面加載
  onLoad: function () {
    utilApi.requestPromise("https://www.bilibili.com/index/ding.json")
    // 使用.then處理結(jié)果
    .then(res => {
      console.log(res.data)
      this.setData({
        myData: res.data
      })
      console.log(this.data.myData)
      this.loadMyData()
    })
  }
})

結(jié)果和使用回調(diào)函數(shù)一致。當(dāng)有多個異步請求時,直接不斷地.then(fn)去處理即可,邏輯清晰。

當(dāng)然,這里只是寫了一個最簡單的Promise函數(shù),還不完整。更完整的Promise化wx.request,等以后業(yè)務(wù)需要再完善吧。另外各種小程序開發(fā)框架也都有了現(xiàn)成的promise化API,拿來即用。

重磅推薦:小程序開店目錄

第一部分:小商店是什么

第二部分:如何開通一個小商店

第三部分:如何登錄小商店

第四部分:開店任務(wù)常見問題

第五部分:小商店可以賣什么

第六部分:HiShop小程序特色功能

第七部分:小程序直播

第八部分:小程序收貨/物流

第九部分:小程序怎么結(jié)算

第十部分:小程序客服

第十一部分:電商創(chuàng)業(yè)

第十二部分:小程序游戲開發(fā)

電話咨詢 微信咨詢 預(yù)約演示 0元開店