服務項目
品牌網站建設

數字營銷

係統平台開發

數字產品

安全運維

Menu
官网开云
官网开云
微信小程序使用Promise實踐
時間:2016-10-17 16:06:00
官方小例子代碼

getUserInfo:function(cb){ var that = this if(this.globalData.userInfo){ typeof cb == "function" && cb(this.globalData.userInfo) }else{ //調用登錄接口 wx.login({ success: function () { wx.getUserInfo({ success: function (res) { that.globalData.userInfo = res.userInfo typeof cb == "function" && cb(that.globalData.userInfo) } }) } }) } },

昨天研究了一下微信小程序的例子,看見了熟悉cb了。我們(men) 好不容易從(cong) cb走向了Promise,如果開發小程序要回到cb中,這是我不能接受的,搞得我昨晚一晚上沒有睡好,今年早一大早就到公司想辦法解決(jue) 問題。

解決(jue) 思路 1、直接使用Promise,我試了一下,是可行的,但這受限於(yu) 運行程序的瀏覽器。不能保證所有瀏覽器都支持Promise。 2、使用第三方庫,bluebird,Q,Defrered等,這樣可以不依賴瀏覽器實現。 說做就做,我最熟悉的是bluebird,於(yu) 是先就在工程文件夾下執行

npm init npm i bluebird --save

得到項目結構如下圖

在App.js中寫(xie) 入

var Promise = require("node_modules/node_modules/js/browser/bluebird.js");

通過調試發現Promise為(wei) undfine,解決(jue) 問題失敗! 深入分析 難道真如網上所說不能加載第三方JS?我覺得應該不可能,如果不能使用第三方程序,什麽(me) 都靠自己寫(xie) ,累都累死。忽然想到一段代碼

logs.js var util = require('../../utils/util.js')util.js module.exports = { formatTime: formatTime }

如果能在logs.js中引入util.js,就一定能引第三方包,隻是我沒有搞清楚這個(ge) 加載機製。看上麵的代碼好像是CMD。我想來想去,最終在瀏覽器發現了這個(ge) 。

define("utils/util.js", function(require, module){var window={Math:Math}/*兼容babel*/,location,document,navigator,self,localStorage,history,Caches;module.exports = { formatTime: formatTime }})

這是瀏覽加載後的代碼,通過代碼分析,總結出如下經驗: 1、原來小程序是自己定義(yi) 了一套加載機製,不是CMD也不是AMD,到有點與(yu) NG相同。 2、小程序會(hui) 為(wei) 每個(ge) js文件加一個(ge) 包頭,每個(ge) 包中都增加一個(ge) window對象,所以在小程序中,window對象是一個(ge) 局部變量。 3、document對象不一定有值 4、require是一個(ge) 函數,module是一個(ge) 對象這點與(yu) CMD一至 再次嚐試 要在小程序中使用第三方包,就必須修改加載頭。當我打開個(ge) bluebird源碼時,立馬就懵逼了,看不懂。所以就選擇了Q,這個(ge) 簡單些,先看沒有修改之樣的。

(function (definition) { "use strict"; // This file will function properly as a <script> tag, or a module // using CommonJS and NodeJS or RequireJS module formats. In // Common/Node/RequireJS, the module exports the Q API and when // executed as a simple <script>, it creates a Q global instead. // Montage Require if (typeof bootstrap === "function") { bootstrap("promise", definition); // CommonJS } else if (typeof exports === "object" && typeof module === "object") { module.exports = definition(); // RequireJS } else if (typeof define === "function" && define.amd) { define(definition); // SES (Secure EcmaScript) } else if (typeof ses !== "undefined") { if (!ses.ok()) { return; } else { ses.makeQ = definition; } // <script> } else if (typeof window !== "undefined" || typeof self !== "undefined") { // Prefer window over self for add-on scripts. Use self for // non-windowed contexts. var global = typeof window !== "undefined" ? window : self; // Get the `window` object, save the previous Q global // and initialize Q as a global. var previousQ = global.Q; global.Q = definition(); // Add a noConflict function so Q can be removed from the // global namespace. global.Q.noConflict = function () { global.Q = previousQ; return this; }; } else { throw new Error("This environment was not anticipated by Q. Please file a bug."); }})(function () { "use strict";

這段代碼,我立馬就看懂了,這就是一個(ge) 標準的閉包,definition是定義(yi) 函數,Q一共適配了CommonJS,RequireJS加載,但可惜能過調試,進入了<script>這個(ge) 分支,原因很簡單,有window對象。但此window不是彼window,所以加載失敗。

想明白了就好改了,改後代碼如下:

(function (definition) { "use strict"; module.exports = definition(); })(function () { "use strict";

需要注意的是definition後麵一定要帶(),表示執行這個(ge) 函數,我一開始沒有執行,結果使用時沒有得到Q對象。原因是definition函數返回Q對象,大家看最一行代碼。 使用Q改寫(xie) 獲取用戶 Q的使用很簡單,主要改了這樣幾處地方

//app.js var Q = require("utils/q.js"); App({ onLaunch: function () { //調用API從(cong) 本地緩存中獲取數據 var logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs) }, globalData:{ userInfo:null }, login : function() { var def = Q.defer(); wx.login({ success : function() { def.resolve(); } }); return def.promise; }, getUserInfo : function() { var that = this; var def = Q.defer(); if( this.globalData.userInfo ) { def.resolve(this.globalData.userInfo); } else { this.login().then(function(){ wx.getUserInfo({ success : function( res ) { that.globalData.userInfo = res.userInfo; def.resolve(res.userInfo); } }); }); } return def.promise; } })

//index.js
//獲取應用實例
var app = getApp()
Page({
  data: {
    motto: 'Hello World',
    userInfo: {}
  },
  //事件處理函數
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad: function () {
    console.log('onLoad')
    var that = this
    //調用應用實例的方法獲取全局數據
    app.getUserInfo().then(function(userInfo){
      that.setData({
        userInfo:userInfo
      })
    });
    console.log(window.document);
  }
})

總結 1、不要先入為(wei) 主,網上的東(dong) 西不能不信,也不能盡信,盡量去自己嚐試。 2、X訊自己造了一個(ge) 封閉的環境,開放?封閉?這個(ge) 東(dong) 西好壞得時間來驗證。 3、得理解包加載機製,基礎的東(dong) 西最重要。

Kaiyun体育官方全站入口服務SERVICE
谘詢
微信掃碼谘詢
電話谘詢
400-888-9358