Let's talk about the conclusion first
Business process: Check from the network log to expire and jump to the login page and ask the user to log in again.
Code logic: Use a custom HttpUtil to encapsulate the API, capture expired tokens globally and process them automatically, and issue them to the upper-level business.
question
Token expiration phenomenon:
In network requests, the client token will expire after a period of time, causing subsequent network requests to fail, and the exception log is thrown as follows:
data: {code: "99997", date: 1634174831325, message: "TOKEN EXPIRED", status: "ERROR"}
The API provided by the mini program is very simple. The developer can check the token expires by itself in the callback function after the request response is successful. The conventional practice:
1. Define the method to check that token expires:
function checkAuth(resp) { if( == '99997') { //The code that expired token returned by our server is 99997, and the code can be customized with the background. ({ url: '/pages/login/login', //Skip to the login page here and ask the user to log in again }) ("Re-login required..."); } }
2. In the response of each request interface, call checkAuth (res) to catch the token expired.
Problem code
function createMatchImage(data, fun) { //(getApp()) ("token = " + getApp().getToken()) ({ method: 'POST', url: + 'match/matchImages', data: data, header: { 'content-type': 'application/json', 'sessionKey': getApp().getToken() }, success: function (res) { (res) (res) // Determine whether the token expires. If it expires, it will jump to the login page. fun(res); } }); } function getMatchImages(id, fun) { ({ ... success: function (res) { (res) ... } }); } function deleteImage(id, fun) { ... ({ ... success: function (res) { (res) fun(res); //return res; } }); }
In the above code, each interface will have duplicate code, such as configuring baseUrl, token, checkAuth(). So here we can further remove duplicate code.
Solution
Unify the entry for network requests and define the HttpUtil class. Packaging method.
const get = (url, success, fail) => { var _token = getApp().getToken() ({ method:'GET', url: baseUrl + url, header:{ 'Authorization': _token, 'content-type': 'application/json', }, success:function(res) { checkAuth(res) // Here, the token is blocked to expire and jump to the login interface (res) success(res) }, fail:function(res){ ("Request failed") fail(res) } }) } ··· = { get: get, post: post }
Use scenarios of HttpUtil:
const httpUtil= require("../common/http/HttpUtil") //The logical layer initiates a network request, and only needs to pass the url and successful callback functions. This is simpler than before.function getActivities(success) { ('meetup/api/v1/activity/getActivityList?pageNo=1&pageSize=100', function(res) { success(res) }) } = { getActivities : getActivities }
As mentioned above, when using httpUtil, the process of handling token expiration is transparent and details are encapsulated inside. At the same time, the business party also omits setting tokens, token expiration processing, baseUrl and other boilerplate codes.
Encapsulation of callback functions using Promise
We can use Promise to eliminate the incoming callback function when calling the request interface.
const get = (params) => { var _token = getApp().getToken() return new Promise((resolve, reject) => { ({ method:'GET', url: concatUrl(params), header:{ 'Authorization': _token, 'content-type': 'application/json', }, success: (res) => { checkAuth(res) // Here, the token is blocked to expire and jump to the login interface resolve(res) }, fail:(err) => { ("Request failed") reject(err) } }) }) }
How to use:
// service layer, define network interfacefunction getActivities() { return ({ url: 'meetup/api/v1/activity/getActivityList?pageNo=1&pageSize=100' }) } /** * Load the activity list (where the group is loaded first to get the activity avatar) */ fetchGroupAndActivities: function(){ if() { var that = this getGroups() //Load the avatar of the group list first. .then((res)=>{ if( == "10000") { ... return getActivities() //Secondly, load the activity list } }) .then((res)=>{ //Chained call, processing activity list data. if ( == "10000") { ... } }) .catch((err) => { //Unified exceptions are caught. Any callbacks in the above then send exceptions will directly interrupt the call chain and process it here. ("get act and group failed...") }) }},
Summarize
During the encapsulation process, baseUrl, token processing, etc. are encapsulated in HttpUtil with Promise objects, hiding implementation details, providing unified interfaces and supporting chain calls to the outside world. This is a common storefront design pattern. The disadvantage is that it violates the principle of opening and closing. If some new intercept request interface processing is added, the original interface implementation must be modified. An intermediate layer can be added later as an interceptor to extend new functions.
This is the article about how WeChat applets deal with the issue of token expiration. For more content on the expired token of token in related applets, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!