文成縣改進(jìn)異步封裝:處理帶返回值的異步調(diào)用 - 邊城客棧

閱讀 41806  ·  發(fā)布日期 2020-08-24 17:26  ·  溫州優(yōu)光網(wǎng)絡(luò)科技有限公司|建站|APP小程序制作|做網(wǎng)站SEO推廣優(yōu)化
【摘要】 最近幾篇文章都跟微信小程序開發(fā)有關(guān),所以有人就問:“小程序不懂啊,能不能寫點(diǎn)別的?”。其實(shí)不用太在意“小程序”這件事情,因?yàn)椤靶〕绦颉痹谖恼轮兄皇且粋€開發(fā)場景,我們實(shí)際解決的問題并非只在小程序中才會遇到,而解決問題的手段完全與小程序無關(guān)!1. 問題在 Proxy 封裝微信小程序的異步調(diào)用 中留下了一個問題:像 wx.r... 【溫州小程序開發(fā),溫州微信公眾號,平陽做網(wǎng)站,平陽網(wǎng)站建設(shè)公司,平陽小程序商城制作,昆陽萬全做網(wǎng)站,鰲江水頭小程序,蕭江騰蛟微信公眾號,山門順溪南雁海西南麂鳳臥麻步懷溪網(wǎng)絡(luò)網(wǎng)店服務(wù),政采云網(wǎng)店管理服務(wù)】...

改進(jìn)異步封裝:處理帶返回值的異步調(diào)用 - 邊城客棧

最近幾篇文章都跟微信小程序開發(fā)有關(guān),所以有人就問:
“小程序不懂啊,能不能寫點(diǎn)別的?”。
其實(shí)不用太在意“小程序”這件事情,因?yàn)椤靶〕绦颉痹谖恼轮兄皇且粋€開發(fā)場景,我們實(shí)際解決的問題并非只在小程序中才會遇到,而解決問題的手段完全與小程序無關(guān)!1. 問題在 Proxy 封裝微信小程序的異步調(diào)用 中留下了一個問題:
像 wx.request() 這種原本就有返回值的情況,該如何封裝呢?如果需要在請求的過程中取消請求,就會用到 wx.request() 的返回值:
const requestTask = wx.request(...);
if (...) {
// 因?yàn)槟承┰蛐枰∠@次請求 requestTask.abort();
}
封裝過后的 awx.request() 會返回一個 Promise 對象,跟 wx.request() 原來的返回值毫無關(guān)系。
如果想要能夠取消請求,就必須將 wx.request() 原來的返回值帶出來,應(yīng)該怎么辦?function wxPromisify(fn) {
return async function (args) {
return new Promise((resolve, reject) => {
const originalResult = fn({
// ^^^^^^^^^^^^^^^^^^^^^^^ // 怎么把 originalResult 帶出去? ...(args || {
}
), success: res => resolve(res), fail: err => reject(err) }
);
}
);
}
;
}
2. 可選方案也不賣關(guān)子了,這里有幾個方案可選:
返回對象或數(shù)組,解構(gòu)后使用。
比如返回 {
promise, originalResult}
或 [promise, originalResult];通過一個“容器”參數(shù)將返回值帶出來,比如 awx.request(params, outBox = {
}
),在處理時為 outBox 賦值:
outBox.originalResult;JS 是動態(tài)類型,可以直接修改 Promise 對象,為其附加屬性:
promise.originalResult = ...。
從使用者的角度來考慮,多數(shù)時候是不需要原返回值的,這時候是肯定是希望 await awx.request(),而不是先解構(gòu)再 await(或 then()),所以,第 1 種方法不可選。
第 2 種方法可行,不需要原返回值的時候,直接使用即可。
但是需要原返回值的時候,稍嫌麻煩,需要先產(chǎn)生一個容器對象傳入。
第 3 種方法使用起來應(yīng)該是最“無感”的。
無論如何,原值隨 Promise 對象帶出來了,用或是不用,請便!現(xiàn)在我們來實(shí)現(xiàn)第 3 種方法,改造 wxPromisify():
3. 失敗的嘗試一開始想得很簡單,原來直接 return new Promise(),現(xiàn)在加個臨時變量應(yīng)該就可以吧:
function wxPromisify(fn) {
return async function (args) {
const promise = new Promise((resolve, reject) => {
// ^^^^^^^^^^^^^^^^ promise.originalResult = fn({
// ^^^^^^^^^^^^^^^^^^^^^^^^^ ...(args || {
}
), success: res => resolve(res), fail: err => reject(err) }
);
}
);
return promise;
// ^^^^^^^^^^^^^^^ }
;
}
然后得到一個錯誤:
TypeError: Cannot set property '
originalResult'
of undefined這個錯很好理解,也很容易改……不過確實(shí)也很容易犯!本來是認(rèn)為 promise 是個局部變量,可以直接訪問,所以在其子作用域中使用是沒問題。
但是這里忽略了這個子作用域是在構(gòu)造函數(shù)中。
來大概分析一下:
new Promise() 需要一個函數(shù)(假設(shè)叫 factory)作為參數(shù),但是這個 factory 執(zhí)行的時機(jī)是什么?注意到 new Promise() 產(chǎn)生 Promise 實(shí)例之后,我們再沒有主動調(diào)用這個實(shí)例的任何方法,所以可以斷定,factory 是在構(gòu)造的過程中執(zhí)行的。
換句話說,這時候 Promise 實(shí)例還沒產(chǎn)生呢,promise 引用的是 undefined。
4. 成功的嘗試既然已經(jīng)知道問題所在,我們接著分析。
構(gòu)造 Promise 實(shí)例的過程中調(diào)用了 factory,而 factory 的在函數(shù)體中直接執(zhí)行了 fn,可以立即拿到 fn 的返回值,所以這個 Promise 實(shí)例構(gòu)造完成之后,是可以拿到原返回值的。
現(xiàn)在來修改一下代碼:
function wxPromisify(fn) {
return async function (args) {
let originalResult;
// ^^^^^^^^^^^^^^^^^^^ const promise = new Promise((resolve, reject) => {
originalResult = fn({
// ^^^^^^^^^^^^^^ ...(args || {
}
), success: res => resolve(res), fail: err => reject(err) }
);
}
);
promise.originalResult = originalResult;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ return promise;
}
;
}
我們需要在 new Promise() 之后對 promise.originalResult 賦值,而這個“值”產(chǎn)生于 new Promise() 的過程中,那么再加個局部變量 originalResult 把它帶出來就好。
搞定!5. 搞笑卻又應(yīng)該嚴(yán)肅對待的事情本來應(yīng)該結(jié)束了,但我猜一定會有人這么干(因?yàn)槲以谄渌麍鼍跋乱娺^):
注意:
下面這個是錯誤示例!function wxPromisify(fn) {
return async function (args) {
let promise = new Promise();
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ promise = new Promise((resolve, reject) => {
// ^^^^^^^^^^ promise.originalResult = fn({
... }
);
// ^^^^^^^^^^^^^^^^^^^^^^ }
);
return promise;
}
;
}
這樣做不會產(chǎn)生前面提到的 TypeError,但是外面拿到的 Promise 對象卻并不攜帶 originalResult。
具體原因跟上面失敗的那次嘗試一樣,所以不再詳述,只提醒一下:
這里產(chǎn)生了兩個 Promise 對象。
6. 再啰嗦一下這次帶出原返回值是以 wx.request() 為例,其返回值的主要用途是提供 .abort() 方法用于取消請求。
這個應(yīng)用場景其實(shí)和 Axios 處理“取消請求 (Cancellation)”類似,所以不妨參考 Axios 通過 cancelToken 實(shí)現(xiàn)的方法。
cancelToken 的實(shí)質(zhì)就是前面提到的第 2 種方法 —— 傳入“容器”對象把需要的東西帶出來。
通過 Promise 對象帶出來和通過一個專門的“容器”對象帶出來,本質(zhì)是一樣的,所以就不多說了。
推薦教程:
《微信小程序》以上就是改進(jìn)異步封裝:
處理帶返回值的異步調(diào)用 - 邊城客棧的詳細(xì)內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
微信
分享相關(guān)標(biāo)簽:
小程序 異步 封裝 promise本文轉(zhuǎn)載于:
segmentfault,如有侵犯,請聯(lián)系[email protected]刪除
上一篇:
微信小程序怎么使用車牌號輸入法
下一篇:
記一次微信小程序在安卓手機(jī)上的白屏問題相關(guān)文章相關(guān)視頻微信小程序開發(fā)初次體驗(yàn)微信小程序常見的開發(fā)問題匯總小程序中wepy-redux的使用以及存儲全局變量微信小程序自動跳出來怎么解決?改進(jìn)異步封裝:
處理帶返回值的異步調(diào)用 - 邊城客棧認(rèn)識小程序的目錄結(jié)構(gòu)小程序的rpx長度單位詳解布局奔牛課堂小程序搜素框 [溫州做小程序]