本博客所有文章采用的授權(quán)方式為 自由轉(zhuǎn)載-非商用-非衍生-保持署名 切揭,轉(zhuǎn)載請(qǐng)務(wù)必注明出處,謝謝锁摔。
聲明:
本博客歡迎轉(zhuǎn)發(fā),但請(qǐng)注明出處廓旬,保留原作者信息
博客地址:孟阿龍的博客
所有內(nèi)容為本人學(xué)習(xí)、研究谐腰、總結(jié)孕豹。如有雷同涩盾,實(shí)屬榮幸
背景
近期,因?yàn)楣ぷ餍枰谘芯课⑿判〕绦颉?br> 微信小程序基本是通過(guò)Javascript+css+wxml(類(lèi)html)組合而成励背。對(duì)于精通前端技術(shù)的人來(lái)說(shuō)春霍,javascript中的promise、callback應(yīng)該是非常熟悉了叶眉,但是對(duì)于javascript小白來(lái)說(shuō)址儒,這類(lèi)技術(shù)還是需要研究。本文即是對(duì)javascript中的這兩個(gè)概念的具體應(yīng)用進(jìn)行舉例分析衅疙。
需求
小程序中的主體邏輯是用js實(shí)現(xiàn)的莲趣,并且小程序中大部分網(wǎng)絡(luò)交互的接口實(shí)現(xiàn)都是異步的,因此在寫(xiě)小程序時(shí)饱溢,不可避免的就必須和異步進(jìn)行打交道妖爷。接下來(lái)舉個(gè)簡(jiǎn)單的例子,來(lái)看看callback和promise在異步接口中的應(yīng)用理朋。
需求舉例:
- 首先我在數(shù)據(jù)庫(kù)的medicine表中插入了3條藥品信息記錄絮识,每條記錄簡(jiǎn)單的包含藥品的一些基礎(chǔ)信息。
- 在小程序中嗽上,我們需要從medicine表中查出所有藥品記錄進(jìn)行展示
解決方案:
- 傳統(tǒng)的方案次舌,我們寫(xiě)個(gè)同步接口,先查數(shù)據(jù)庫(kù)再進(jìn)行數(shù)據(jù)輸出即可
- 但是在小程序中兽愤,微信提供的數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)接口都是異步的彼念,因此不能用簡(jiǎn)單的同步模式寫(xiě)代碼,這時(shí)就需要使用callback或者promise
實(shí)現(xiàn)方案1:傳統(tǒng)同步模式
按照同步模式的理解浅萧,以上代碼第8行逐沙,調(diào)用this.getDbData函數(shù)查詢(xún)數(shù)據(jù)庫(kù),在函數(shù)內(nèi)將查詢(xún)結(jié)果賦值給全局變量data中的medicine中洼畅,并輸出查詢(xún)結(jié)果
-
第9行吩案,在調(diào)用了getDbData函數(shù)之后,再輸出變量data的內(nèi)容帝簇,發(fā)現(xiàn)medicine變量并沒(méi)有被賦值徘郭,如下圖
image.png 從上邊的執(zhí)行結(jié)果可以看到,第9行先執(zhí)行了丧肴,getDbData中的輸出還后執(zhí)行了
這就是因?yàn)間etDbData中調(diào)用數(shù)據(jù)庫(kù)的接口残揉,在微信API中是異步實(shí)現(xiàn)的,因此要想實(shí)現(xiàn)查詢(xún)獲取了相關(guān)數(shù)據(jù)之后芋浮,再對(duì)數(shù)據(jù)做進(jìn)一步處理就需要使用callback機(jī)制或者promise
實(shí)現(xiàn)方案2:callback模式改造
- 如上抱环,在第8行增加了this.process_data作為callback傳入getDbData函數(shù)中
- 第12~14行,是callback函數(shù)的定義,并在該函數(shù)中輸出相關(guān)全局變量的內(nèi)容
-
第25行镇草,是執(zhí)行完數(shù)據(jù)庫(kù)查詢(xún)并且完成全局變量賦值之后眶痰,將全局變量傳給callback函數(shù)并調(diào)用,整體執(zhí)行結(jié)果如下:
image.png
實(shí)現(xiàn)方案3:promise模式改造
- 如上陶夜,第15行重新定義了promise模式的函數(shù)凛驮,getDataByPromise返回的是一個(gè)promise對(duì)象
-
在第7行調(diào)用函數(shù)之后,在then中執(zhí)行相關(guān)后置動(dòng)作条辟,具體執(zhí)行效果如下:
image.png
以上黔夭,即為這幾種模式的對(duì)比。
附羽嫡,完整代碼:
Page({
data: {
"medicine": "N/A",
},
onLoad: function (options) {
// callback模式處理異步調(diào)用
// var that = this;
// this.getDbData("medicine", {}, "medicine", this.process_data)
// console.log("in onLoad:", this.data)
// promise模式處理異步調(diào)用
this.getDataByPromise("medicine", {}).then((data) => {
this.setData({
"medicine": data
})
console.log("in onLoad promise:", this.data)
})
},
getDataByPromise: function (coll_name, search_cond) {
var promise = new Promise((resolve, reject) => {
var that = this;
const db = wx.cloud.database();
db.collection(coll_name).where(search_cond).get({
success: function (res) {
console.log("in promise info:", res.data)
resolve(res.data)
},
error: function (e) {
console.log(e)
reject("查詢(xún)數(shù)據(jù)庫(kù)失敗")
}
});
});
return promise;
},
process_data: function(data){
console.log("in onLoad callback:", this.data)
},
getDbData: function (coll_name, search_cond, data_key, cb) {
const db = wx.cloud.database()
var that = this;
var ready_data = {};
db.collection(coll_name).where(search_cond).get({
success: function (res) {
ready_data[data_key] = res.data;
that.setData(ready_data);
console.log("查詢(xún)數(shù)據(jù)庫(kù)完成:", that.data, res.data);
cb(that.data)
}
})
}
})