《微信小程序開發之異步轉同步》

問題概述

基于小程序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后才開始的,這樣就達到了我們的目的,問題解決。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。