標籤:問題 prototype 前端 func 預設 請求 情境 成功 ghost
背景:
- HybridApp,前端採用JS-bridge的方式調用Native的介面,如擷取裝置資訊、拍照、Face Service等
- 前端封裝了調用庫,每次調用Native介面,需要進行兩步操作(1、在window下掛載Native回呼函數;2、調用InvokeNative函數,發送請求資料)
改造前:
使用回調,在每次調用Ygritte中的方法前,必須先定義好回呼函數,掛載在window[funcName]上。然後調用。
問題:
1、可能導致回調地獄:比如某個情境中,需要先判斷App版本,然後調用不同的Native介面,那麼就需要在回調中再次定義回調,產生嵌套;
2、無法改為同步:比如的情境中,在進入Home頁面,在 [created] 中需要判斷App版本,如果版本過低,在 [mounted] 中需要提示。使用回調的方式,理論上存在mounted執行時, [created] 中的回調還沒有執行。
改造:
- 使用Promise對調用和回調進行改造
- 為保證舊代碼相容,不修改原來在Ygritte中使用原型中添加介面的形式
- 回呼函數的定義封裝,在回調中執行resolve
/** * 獲得使用者簽名資料 * @param {Float} lineWidth 如"1.5",傳0或者null則視為使用native預設值 * @param {String} lineColor 畫筆顏色值的字串,不帶#號,如:"666666",傳Null 字元串或null則視為使用native預設值 * @param {String} callbackName 回調手寫簽名的圖片,原圖、背景透明、為base64編碼的字串,key為"signatureImage";如果使用者取消,則回調空json * @version: from app version 2.4.0 */Ygritte.prototype.getHandWritingSignature = function(lineWidth, lineColor, callbackName){ var args = [‘knowNothing‘, ‘getHandWritingSignature‘, callbackName || ‘‘, { lineWidth: lineWidth, lineColor: lineColor }]; snow.invokeNative(args);};
不修改上方原有的函數,新增下方函數封裝
/** * 校正App傳回值,避免多次回調,只執行一個resolve的問題 * Promise的定義中一旦resolve或者reject,就不會執行後面的resolve和reject * * getPhoto: 成功擷取圖片資料時,會回調兩次,一次參數為圖片值,一次參數為undefined * * @param {string} method * @param {object} res * @returns */function checkNativeReturn(method, res) { if (method === ‘getPhoto‘ && (!res || ‘{}‘ === JSON.stringify(res))) return false; return true;}/** * Promise化的方法調用 * * 白靈(Ghost)是瓊恩·雪諾 的白色冰原狼 ,外觀像狐狸。它的毛色淨白,眼瞳紅如鮮血。 * * @param {object} { method, key = method, data } * @returns */function Ghost({ method, key = method, data }) { return new Promise((resolve, reject) => { if (Ygritte[method] && typeof(Ygritte[method]) === ‘function‘) { // 全域掛載App回呼函數 window[key] = (res) => { if (checkNativeReturn(method, res)){ resolve(res); window[key] = () => {}; } else { reject(res); } }; var args = [‘knowNothing‘, method, key || ‘‘, data]; snow.invokeNative(args); } else { reject(new Error(‘不存在的Native方法,請檢查method‘)); } });}
改造後:
1、使用promise封裝,避免在業務代碼中出現在全域掛載函數的行為
2、可以使用async文法,代碼錶意更清晰
遺留:
1、部分Native介面調用後,會執行兩次回調,原來是在業務代碼中進行判斷。Promise化後需要用代碼磨平,因為Promise中resolve函數只會執行一次,無法保證第一次執行的是業務需要的參數。
【筆記】HybridApp中使用Promise化的JS-Bridge