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了。我們好不容易從cb走向了Promise,如果開發(fā)小程序要回到cb中,這是我不能接受的,搞得我昨晚一晚上沒有睡好,今年早一大早就到公司想辦法解決問題。
解決思路 1、直接使用Promise,我試了一下,是可行的,但這受限于運行程序的瀏覽器。不能保證所有瀏覽器都支持Promise。 2、使用第三方庫,bluebird,Q,Defrered等,這樣可以不依賴瀏覽器實現(xiàn)。 說做就做,我最熟悉的是bluebird,于是先就在工程文件夾下執(zhí)行
npm init
npm i bluebird --save
得到項目結構如下圖
在App.js中寫入
var Promise = require("node_modules/node_modules/js/browser/bluebird.js");
通過調試發(fā)現(xiàn)Promise為undfine,解決問題失敗! 深入分析 難道真如網上所說不能加載第三方JS?我覺得應該不可能,如果不能使用第三方程序,什么都靠自己寫,累都累死。忽然想到一段代碼
logs.js
var util = require('../../utils/util.js')
util.js
module.exports = {
formatTime: formatTime
}
如果能在logs.js中引入util.js,就一定能引第三方包,只是我沒有搞清楚這個加載機制??瓷厦娴拇a好像是CMD。我想來想去,最終在瀏覽器發(fā)現(xiàn)了這個。
define("utils/util.js", function(require, module){var window={Math:Math}/*兼容babel*/,location,document,navigator,self,localStorage,history,Caches;
module.exports = {
formatTime: formatTime
}
})
這是瀏覽加載后的代碼,通過代碼分析,總結出如下經驗: 1、原來小程序是自己定義了一套加載機制,不是CMD也不是AMD,到有點與NG相同。 2、小程序會為每個js文件加一個包頭,每個包中都增加一個window對象,所以在小程序中,window對象是一個局部變量。 3、document對象不一定有值 4、require是一個函數(shù),module是一個對象這點與CMD一至 再次嘗試 要在小程序中使用第三方包,就必須修改加載頭。當我打開個bluebird源碼時,立馬就懵逼了,看不懂。所以就選擇了Q,這個簡單些,先看沒有修改之樣的。
(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";
這段代碼,我立馬就看懂了,這就是一個標準的閉包,definition是定義函數(shù),Q一共適配了CommonJS,RequireJS加載,但可惜能過調試,進入了<script>這個分支,原因很簡單,有window對象。但此window不是彼window,所以加載失敗。
想明白了就好改了,改后代碼如下:
(function (definition) {
"use strict";
module.exports = definition();
})(function () {
"use strict";
需要注意的是definition后面一定要帶(),表示執(zhí)行這個函數(shù),我一開始沒有執(zhí)行,結果使用時沒有得到Q對象。原因是definition函數(shù)返回Q對象,大家看最一行代碼。 使用Q改寫獲取用戶 Q的使用很簡單,主要改了這樣幾處地方
//app.js
var Q = require("utils/q.js");
App({
onLaunch: function () {
//調用API從本地緩存中獲取數(shù)據(jù)
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: {}
},
//事件處理函數(shù)
bindViewTap: function() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad: function () {
console.log('onLoad')
var that = this
//調用應用實例的方法獲取全局數(shù)據(jù)
app.getUserInfo().then(function(userInfo){
that.setData({
userInfo:userInfo
})
});
console.log(window.document);
}
})
總結 1、不要先入為主,網上的東西不能不信,也不能盡信,盡量去自己嘗試。 2、X訊自己造了一個封閉的環(huán)境,開放?封閉?這個東西好壞得時間來驗證。 3、得理解包加載機制,基礎的東西最重要。