上回寫到:
沒看上回的同學,在這裏!
// utils/async.js
function wxPromisify(fn) {
return async function(args) {
return new Promise((resolve, reject) => {
fn({
...(args || {}),
success: res => resolve(res),
fail: err => reject(err)
});
});
};
}
export function toAsync(names) {
return (names || [])
.map(name => (
{
name,
member: wx[name]
}
))
.filter(t => typeof t.member === "function")
.reduce((r, t) => {
r[t.name] = wxPromisify(wx[t.name]);
return r;
}, {});
}
// pages/somepage/somepage.js
import { toAsync } = require("../../utils/async");
// ...
const awx = toAsync(["login", "request"]);
await awx.login();
await awx.request({...});
這不已經封裝過了嗎?
這回寫的是不一樣的封裝。因爲,一個小程序裏要寫好多個 toAsync
調用,真的很煩吶!
能不能一次封裝,到處調用?能!把所有用到的方法都在初始化的時候封裝起來。可是,難免會有遺漏。
能不能一次封裝,到處調用,還不需要初始化?
能!祭出 Proxy 大神:
// utils/asyncjs
function wxPromisify(fn) { ... } // 前面已經定義過了
export function asyncProxy(target) {
return new Proxy(target, {
cache: {},
get(it, prop) {
const aFn = this.cache[prop];
if (aFn) { return aFn; }
const v = it[prop];
if (typeof v !== "function") {
return v;
}
return this.cache[prop] = wxPromisify(v);
}
});
}
// app.js
import { asyncProxy } from "./utils/async";
App({
onLaunch: function() {
wx.awx = asyncProxy(wx);
// ....
}
})
// pages/somepage/somepage
// ...
const { awx } = wx;
await awx.login();
await awx.request({...});
解釋:
因爲 awx
是代理的 wx
對象,調用 awx.login()
的時候,實際是先調用代理的 get(wx, "login")
,找到用來代替 wx.login
的東西。
根據上面代碼裏的邏輯,先從 cache
裏找使用 wxPromisify()
封裝的結果,若有,直接返回;若沒有,先封裝成 Promise 網絡的函數,存入 cache
,再返回。
直觀一點描述,大概是這樣:
awx.login();
^^^^^^
get(wx, "login")
最後出個題:像 wx.request()
這種原本就有返回值的情況,該如何封裝呢?
喜歡此文,點個**