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) 西最重要。