前言
ES6 標準的 Promise
解決了 Javascript 程式碼中比較常見的回撥地獄問題,搭配 async
/await
可以用同步的方式寫非同步邏輯,大大提高了開發效率。
但是至今仍有很多庫沒有實現 Promise
化的介面,其中就包括微信小程式的 api。
為了不向惡勢力妥協,寫出風格統一的程式碼,我們有必要了解何為 Promise。
本文假定讀者有一定 JavaScript 基礎,同時瞭解 Promise
的基本用法。
回撥介面
非同步回撥介面指的是通過傳遞函式來處理非同步方法呼叫,一般有兩種方式。
-
小程式方式
分別傳遞成功和失敗的回撥以處理兩種不同情況
wx.showToast({ title: 'Hello, world', success: () => console.log('success'), fail: () => console.log('failure'), }) 複製程式碼
-
MongoDB 方式
傳遞一個以 error 為首引數的回撥用以鑑別是否呼叫成功
db.find({ name: 'Idan Loo' }, (err, data) => { if (err) { // err 是呼叫失敗的原因 console.log(err) return } // data 就是非同步傳遞回來的引數 console.log(data) }) 複製程式碼
兩種方式各有千秋,這裡僅討論微信方式,MongoDB 方式的介面 Promise
化相信各位可以舉一反三。
Promise 化
簡單實現
以 showToast
為例
const showToast = option =>
new Promise((resolve, reject) =>
wx.showToast({...option,
success: resolve,
fail: reject,
})
)
showToast({ title: 'Hello, Promise' })
.then(() => console.log('success'))
.catch(() => console.log('failure'))
複製程式碼
你已經知道了如何 Promise
化小程式的介面,現在你只需要重複上面的程式碼,將所有你需要用到的介面改為 Promise
的即可。
高階一點的實現
複製貼上一把梭雖然快,但是作為一名程式設計師,自然應該追求更簡潔的實現。
通過觀察,小程式所有的非同步介面都採用了相同的形式,並且都位於 wx
物件中,故我們可以抽象出通用的 promisify
方法用以 Promise
化小程式的介面
const promisify = name => option =>
new Promise((resolve, reject) =>
wx[name]({...option,
success: resolve,
fail: reject,
})
)
const showToast = promisify('showToast')
const request = promisify('request')
複製程式碼
現在只需一行程式碼,就可以 Promise
化小程式的介面,趕緊把之前寫的醜陋的回撥程式碼改過來吧!
更高階的實現
如果你跟我一樣,程式碼潔癖到上述程式碼都接受不了的話,那恭喜你,通過 Proxy 可以更好的實現我們的目標。
const pro = new Proxy(wx, {
get(target, prop) {
return promisify(prop)
}
})
pro.showToast({ title: 'Hello, world' }).then(...)
pro.request({ url: 'https://github.com' }).then(...)
複製程式碼
在 promisify
方法的基礎上,給 wx
物件加了個代理,現在你可以像使用 wx
物件一樣使用 pro
,並且所有的非同步方法都變成了 Promise
形式的!
無需實現
最好的實現就是交給別人實現,正好我已經把前文中的程式碼打包上傳, minapp-promise,不足 1k,開箱即用。
能看到這裡著實不易,希望你們能給我點個贊,順便在 GitHub 給我個星星就更好了。
手機碼字,如有錯漏,萬望斧正。