This is the 12th day of my participation in Gwen Challenge
preface
After writing an article about the unbeatable encapsulation of the request module in the field project last time, I put a serious problem affecting the user experience on the agenda.
You can work with me to improve the request module after reading the above article.
How to cancel Pomrise?
scenario
Left and right page layout, click the element in the task list on the left to obtain the task details on the right.
In this scenario, normal testing is fine, but frequent toggling and clicking on the left task list can create a serious experience problem.
Since the getTaskDetail function is run after clicking on the left, the logic is as follows.
- The details page on the right is displayed
loading
. - Gets the filter criteria.
- Request the interface to get the ID or other value based on the clicked task.
- Get the data returned by the interface and assign it to the page variable.
- The details page on the right is closed
loading
.
async getTaskDetail() {
this.rightLoading = true
const httpObj: HttpObj = await this.checkHttpObj()
const {
data: { checklists, students },
meta: { school_alias, checklist_form },
} =fetch("task.detail", { school_id: this.activeSchoolId, ... httpObj })this.rightDetail = {
checklists,
students,
school_alias,
checklist_form,
}
this.rightLoading = false
}
Copy the code
troubled
As shown in the preceding function, frequent clicking on the left will cause problems with detailed data and loading display/hiding, and waste requested network resources.
How do I cancel the first Get Promise when I click for details the second time?
How do I resolve the case where I cancel promises and process different aliases at the same time?
parsing
One way to think about it is that each requested interface alias is unique, and we need to know which alias is being requested and then cancel the requested Promise.
- Create a local object to store the requested object
Promise
.
interface FetchHashMap = {
[aclAlias: string] :Promise<Response>
}
fetchHashMap:FetchHashMap = {}
Copy the code
- Add a few functions to handle it
A Promise for the alias interface is being requested
.
hasFetchData(aclString: string) :boolean {
return this.fetchHashMap[aclString] ? this.fetchHashMap[aclString] : false
}
deleteFetchData(aclString: string) {
delete this.fetchHashMap[aclString]
}
setFetchData(aclString: string, promise: Promise<any>) {
this.fetchHashMap[aclString] = promise
return this.fetchHashMap[aclString]
}
Copy the code
- The following code is the request module encapsulated in the previous article. We are the first
4
Continue to improve.
/** * Simple encapsulation *@params {string} Route alias *@params {Object} Pass argument *@return Response* * /
async fetch(aclString: string, httpObj? :Object, paramsObj? :Object){...// Get the routing data according to the alias, then check whether there are routing parameters
if (isHaveRouteParams) {
...
if (paramsSuccess) {
const result = await fetchPost(aclString, routeHttpObj, method, postHttpObj, paramsObj)
return result
} else {
console.error(routesArray)
console.error("Parameter passed in incomplete or parameter value is null.")}}else {
// No routing parameters are requested directly
const result = await fetchPost(aclString, {}, method, httpObj, paramsObj)
return result
}
}
Copy the code
- Put the final request
Promise
Separate it out.
/** * reduce the same code, unified request interface *@param {string} AclString Permission ACL *@param {object} RouteHttpObj Route alias parameter *@param {string} Method Request method *@param {object} PostHttpObj Post parameter *@param {object} ParamsHttpObj Route suffix parameter *@return {Promise<Response>} Result Return parameter **/ after the request interface
async fetchPost(aclString: string.routeHttpObj: any.method: string.postHttpObj: any.paramsHttpObj: any) :Promise<any> {
let httpUrl: any = Object.keys(routeHttpObj).length ? await this.getApi(aclString, routeHttpObj) : await this.getApi(aclString)
if (paramsHttpObj && Object.keys(paramsHttpObj).length) {
const paramsUrl: string = this.getQueryObject(paramsHttpObj)
httpUrl = `${httpUrl}?${paramsUrl}`
}
const result: any = this.fetchPostWrap(this.http[method](httpUrl, postHttpObj).toPromise())
return result
Copy the code
-
Add logic to the requesting function.
(1). The requested Promise is passed into the module.
(2). Check whether the current request alias exists in fetchHashMap.
(3). If there is a request for the same alias, we need to break its Promise.
(4). If no request for the alias is pending, no request for the alias is pending.
(5). Then process the current request and return a Promise as normal.
(6). Delete the current request recorded in fetchHashMap before returning the result.
asyncfetchPost(...) :Promise<any> {...let abort, fetchPromise
// Use promise.race to cancel the Promise
// Race () returns a Promise that fails or succeeds, regardless of other promises
const result: any = Promise.race([
this.http[method](httpUrl, postHttpObj).toPromise(),
new Promise((resolve, reject) = > {
abort = reject
}),
])
// Pull out the reject in race that cancels promises for subsequent calls
result.abort = abort
// When a request comes in, determine whether a request with a unique alias is being requested. If so, abort is run.
if ((fetchPromise = this.hasFetchData(aclString))) {
fetchPromise.abort({})
}
// Record the Promise of the current request
fetchPromise = this.setFetchData(aclString, result)
// Return the request result normally
return fetchPromise
.then((res) = > {
// When a request Promise is returned, the requested Promise is pushed out.
this.deleteFetchData(aclString)
return res
})
.catch((error) = > error)
}
Copy the code
Call it a day.
The last
Give me a thumbs up before I leave.
In addition to promote their own interview series, update
Interviewer: Do you know Callback Hell?
Interviewer: What’s the difference between react and Vue?
Interviewer: Do you know anything about ES6?
Interviewer: Do you know anything about Webpack?
Interviewer: Have you ever written a loader and separated modules while using WebPack?
Interviewer: How to correctly identify data types in Javascript?