先来看一段代码,就是一小段而已: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 || "登陆时发生错误"); } } }
喜欢此文,点个赞 ⇙
支持做者,赏个咖啡豆 ⇓