小程式點睛之一:如何將小程式非同步回撥介面 Promise 化

Idan Loo ?發表於2019-01-22

前言

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 給我個星星就更好了。

手機碼字,如有錯漏,萬望斧正。

相關文章