This article introduces three types of asynchronous network requests: xmlhttprequest, promise, and async await, among which async await allows us to write asynchronous programs in a similar way and get rid of cumbersome functions.
In order to cope with more and more testing needs and reduce repetitive work, Youdao Intelligent Hardware Test Group has developed a series of test efficiency improvement tools based on electron.
With the rapid development and iteration of tools, more and more nested functions are presented, and the probability of tool crashes is increasing. In order to solve these problems,We refactored these functions with async awaitAs a result, the number of ** has decreased, and the readability and comprehensibility of ** have been greatly improved.
This article describes:There are three types of asynchronous network requests: xmlhttprequest, promise, and async awaitwhere the async await notation allows us to write asynchronous programs in a way similar to synchronously, getting rid of cumbersome functions.
In JS, if it's not complicated to make a single network request, you can use Fetch, Axios, or just xmlhttprequest.
However, if multiple requests pull data sequentially, it is very troublesome to write, because the network requests in JS are asynchronous and want to be executed sequentiallyThe most common way to write this is to make the next request in the ** function, as follows:
const requestoptions = )
catch(error => console.error('error', error));
catch(error => console.error('error', error));
Let's say I need to go through two steps to get a piece of data, such as getting a data object from data, via dataid to get the number I want to get the data, and then send another request to get the data I want. The way of using the ** function is similar to the above, which is too cumbersome, and easy to make mistakes, and once the logic is complicated, it is not easy to change.
Next, let's sort out several network request methods of js, get rid of **hell, and hope to help those who encounter similar problems.
The first is xmlhttprequest, which is what the famous ajax used to refer to when I first learned the frontend. The following is the procedure for creating a network request through the xmlhttprequest object
Let's say a visit to http: localhost:3000 user returns a JSON object.
const xhr = new xmlhttprequest();
const url = 'http://localhost:3000/user'
xhr.onreadystatechange = function()
xhr.open('get',url)
xhr.send()
This paragraph first creates an xmlhttprequest object xhr and then gives xhrOnReadyStateChange adds the ReadyStateChange function for the ReadyStateChange event, followed by xhropen('get', url) to initialize the request, and finally by xhrsend() to send the request.
After the request is sent, the program continues to execute without blocking, which is also the benefit of asynchronous calls. When the browser receives a response, it goes to xhronReadyStateChange. Throughout the request process, xhrOnReadyStateChange is triggered four times, and each time the ReadyState will self-increment, from 1 to 4, and the final response data will only be available at the final stage, when the ReadyState is 4.
After reaching the fourth stage, you also need to determine whether the status code of the response is normal based on the status, usually the response code is 200, which means that the request has not encountered problems. This ** will eventually hit youdao on the console.
It can be seen that if you want to process requests through xmlhttprequest, you must first create an xmlhttprequest object for each request, and then bind the ** function of the readystatechange event to each object.
Promises were introduced in ECMAScript 2015, and if one event depends on the result returned by another event, using it can be complicated.
The promise object provides a pattern for checking for the failure or success of an operation. If successful, another promise is returned. This makes the writing of ** more standardized.
Here's how to handle it through promises:
const promise = new promise((resolve,reject)=> else
then( msg => console.log(msg))
catch( err => console.error(err))
finally( _=>console.log("finally"))
The above paragraph strings together the whole process, first create a promise object, its constructor receives a function, the first argument of the function is the function to be executed when there is no error, the second argument is the function to be executed after the error, r eject.
resolve refers to the ** function in then after the successful execution, and reject refers to the ** function executed in catch after the execution fails. The final is executed regardless of success or failure, and can be used to put the finishing touches on some cleanup.
Promise-based network requests can be implemented using the Axios library or the browser's native fetch.
The Axios library creates a request as follows:
import axios from 'axios'
const url = ''
axios.get(url)
then(data => console.log(data))
catch(err => console.error(err))
I prefer to use fetch, fetch is a browser API used instead of xmlhttprequest, it doesn't need a library, fetch creates requests in a similar way to axios, and it is not repeated as shown at the beginning.
Although promises simplify the way functions are written, they still don't get rid of hell, and if multiple requests are strung together, a new promise will be created in then as I wrote at the beginning, and eventually it will become a promise hell.
Async Await was introduced in ECMASpoc 2017 to simplify the way promises are written, making asynchronous function calls in ** sequential and easy to understand. Let's use the example at the beginning:
Get the data directly with fetch:
const requestoptions = )
catch(error => console.error('error', error));
catch(error => console.error('error', error));
After overriding with async await:
async function demo()
const response = await fetch('', requestoptions);
const data = await response.json()
const response1 = await fetch(''+data.id, requestoptions)
const data1 = await response1.json()
console.log(data1)
demo().catch(error => console.error('error',error))
The rewritten ** is not very clear, there are not so many then followed, so that if there is a series of network requests, there is no need to be afraid.
When async is placed before the declaration of a function, the function is an asynchronous function, and calling the function returns a promise. await is used to wait for a promise object, it can only be used in asynchronous functions, and the await expression will pause the execution of the current asynchronous function and wait for the promise processing to complete.
In this way, if you want a series of asynchronous functions to be called sequentially, you can simply put the called functions into a function decorated with async, and add await before the call to make these functions execute obediently in order.
Through the combing of this article, I believe you already know how to avoid ** hell. However, it should be noted that promise was added to the language specification in 2015, and async await was added to the language specification in 2017, if your project is older or must be compatible with older browsers (such as IE6), then you need to solve the **hell in another way.
As long as you are using a version of Electron that has been supported in recent years, Electron can be thought of as Chromium and NodeA combination of JS, ideal for writing cross-platform utility desktop applications.