Let’s start with a little piece of code, just a little bit:

Export function loginWithWx() {wx.showLoading({title: "Loading...") {wx.showLoading(); }); 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 | | "an error occurred while trying to login"); wx.hideLoading(); }}, fail: res => {showMessage(" Request timeout, please try again later "); }}); wx.hideLoading(); }, fail: res => { console.log(res); }}); wx.hideLoading(); }

At first glance, this code looks perfect. But if you think about it a little bit, you can see the problem.

First, the most obvious problem: too deep indentation. The deepest indentation is 24 Spaces, or 6 levels. We generally believe that indentation is easier to read up to 3 levels, and the “Extract Method” Method should be considered for refactoring beyond 3 levels.

Next, look at the outer logic:

wx.showLoading()
wx.login()
wx.hideLoading()

This is the expected order of execution.

Note that wx.login is an asynchronous process, so hideLoading() does not actually wait for the login process to complete before turning off the load prompt. So the second problem is ignoring the order of asynchronous execution.

You can immediately think of using the complete parameter wx.login() to resolve this:

wx.showLoading();
wx.login({
    complete: () => wx.hideLoading()
});

But that leads to the next question: complete is too fast!

Why is that? Let’s clean up the internal logical structure again:

wx.login({
    success: () => {
        wx.request({
            success: () => { },
            fail: () => { }
        })
    },
    fail: () => { }
})

Note that wx.request is still an asynchronous process, so the success of wx.login ends immediately, triggering Complete. At this time wx.request may still be waiting for the server to respond.

So should I put wx.hidloading () into the internal logic? Technically, yes!

But the reality is that there are many branches of internal logic, deep and deep, both synchronous logic and asynchronous logic…… You need to be very careful about where you put it. In fact, the code in the example already puts some wx.hidloading () in the internal logic, but

  1. Incomplete coverage;
  2. Because the outermost layerhideLoading()Pre-execution, it’s not working.
  3. Normative constraints are violated: Pair logic should try to avoid one-to-many situations.

To explain point 3, a showLoading() should correspond to only one HideLoading (). Given the complexity of the logic, this is not a mandatory constraint rule, but it should be avoided.

And the way you do that is, you refactor, you break the internal logic out; Then, take the completion event processing logic as a parameter and pass it through layer by layer:

function appLogin(params, complete) { // ^^^^^^^^ wx.request({ ... params, complete: complete // ^^^^^^^^ }); } function wxLogin(params, complete) { // ^^^^^^^^ wx.login({ ... params, success: () => appLogin({}, complete), // ^^^^^^^^ fail: () => complete() // ^^^^^^^^^^ // complete: Complete // university // note that the complete event cannot be used directly because of the asynchronous processing in success and fail. // The reasons have been explained above. }); } wx.showLoading(); wxLogin({}, () => wx.hideLoading()); // ^^^^^^^^^^^^^^^^^^^^^^ pass complete

Obviously, in the current technology environment, this is not optimal, and you can still optimize it — encapsulate it anyway, just encapsulate it as a Promise. This is then converted to a synchronous syntax via the await call, which is much easier to handle. The specific process of encapsulation has been explained in detail in the previous two articles, so I won’t repeat it here. Anyway, we’ve wrapped the asynchronous version of WX, AWX, for use here:

Export async function asyncloginWithWx () {wx.showLoading({title: "Loading"); }); try { return await internalProcess(); } catch (err) {showMessage(" Request timeout, please try again later "); } finally { wx.showLoading(); } // Encapsulate the internal logic with a local function, // mainly to make the 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 | | "an error occurred while trying to login"); }}}

Please pay attention to the official account Bian Cheng Inn finished product

After reading, don’t go first, point a praise ⇓, praise a line!