先來看一段代碼,就是一小段而已:api
export function loginWithWx() { wx.showLoading({ title: "登陸中..." }); wx.login({ success: res => { wx.request({ url: `${apiRoot}wx/${res.code}`, method: "get", success: res => { const { data } = res; const jwt = app.globalData.jwt = data?.jwt; if (jwt) { wx.reLaunch({ url: "../index/index" }); wx.hideLoading(); } else { showMessage(data.message || "登陸時發生錯誤"); wx.hideLoading(); } }, fail: res => { showMessage("請求超時,請稍後重試"); } }); wx.hideLoading(); }, fail: res => { console.log(res); } }); wx.hideLoading(); }
這段代碼乍一看,彷佛沒毛病。可是稍微思考一下,就能發現問題了。服務器
首先,最直觀的問題:縮進太深。縮進最深的地方是 24 個空格,也就是 6 層。通常咱們認爲 3 層之內的縮進比較容易閱讀,超過 3 層應該考慮使用「Extract Method」方法進行重構。app
接下來,看外層邏輯:異步
wx.showLoading() wx.login() wx.hideLoading()
這是指望的執行順序。async
注意到 wx.login
是一個異步過程,因此實際上 hideLoading()
並不會等登陸過程結束就關閉了加載提示。因此第 2 個問題是忽略了異步執行的順序。ide
立刻能夠想到使用 wx.login()
的 complete
參數來解決:函數
wx.showLoading(); wx.login({ complete: () => wx.hideLoading() });
不過立刻就引出了下一個問題:complete 仍是太快!優化
爲何?咱們再把內部的邏輯結構清理出來:url
wx.login({ success: () => { wx.request({ success: () => { }, fail: () => { } }) }, fail: () => { } })
注意到 wx.request
仍然是一個異步過程,因此 wx.login
的 success
會當即結束,觸發 complete
。而這時候 wx.request
可能還在等待服務器響應。3d
那麼是否是應該把 wx.hideLoading()
放到內部邏輯中去?理論上來講,是的!
但實際狀況是,內部邏輯分支較多,深次較深,既有同步邏輯,也有異步邏輯……考慮應該放在哪些地方,須要很是的謹慎。實際上,案例中的代碼就已經在內部邏輯中放了一些 wx.hideLoading()
,只不過
hideLoading()
提早執行,失效了。解釋一下第 3 點,就是說:一個 showLoading()
最好只對應一個 hideLoading()
。考慮到邏輯的複雜性,這不是強制約束規則,但應該儘可能去避免。
處理的辦法是,重構,將內部邏輯拆分出來;而後,將完成事件處理邏輯做爲一個參數,一層層的往裏傳:
顯然在當前的技術環境中,這並非最優方案,還能夠繼續優化——反正都要封裝,乾脆封裝成 Promise。而後經過 await
調用轉換成同步語法,處理起來會輕鬆得多。封裝的具體過程在前兩篇文章中有詳細的講解,這裏就不贅述了。總之,咱們封裝了 wx
的異步版本 awx
,在這裏用就好:
export async function asyncLoginWithWx() { wx.showLoading({ title: "登陸中..." }); try { return await internalProcess(); } catch (err) { showMessage("請求超時,請稍後重試"); } finally { wx.showLoading(); } // 把內部邏輯用個局部函數封裝起來, // 主要是爲了讓 try ... catch ... 看起來清晰一些 async function internalProcess() { const { code } = await awx.login(); const { data } = awx.request({ url: `${apiRoot}wx/${code}`, method: "get", }); const jwt = app.globalData.jwt = data?.jwt; if (jwt) { wx.reLaunch({ url: "../index/index" }); } else { showMessage(data.message || "登陸時發生錯誤"); } } }
喜歡此文,點個贊 ⇙
支持做者,賞個咖啡豆 ⇓