Introduction to Asynchronous Processing in JavaScript
2024.3.9
2018.4.21
JavaScript allows asynchronous processing using Promise. I have always only written programs that run on the server, so I have never done asynchronous processing on the client, but I would like to use Promise and async/await because it would be very difficult to do everything on the main thread.
When Promise should be used
Asyncrhnous communication
Since communication takes time, executing on the main thread will put other processes on hold until the result is returned. This is very inconvenient, so asynchronous execution is recommended when using the Web API.
Execute processes in parallel
When multiple functions are combined, they must be executed in the correct order or variables will be undefined
. To avoid this, callback functions can be used, but the more complex the process becomes, the more nested it becomes and the less readable it becomes.
Using Promise seems to be easier to understand than using callback functions, and async/await makes it even simpler.
What's AJAX
XMLHttpRequest is a confusingly named XMLHttpRequest, but it is used for Web APIs, such as JSON, as it is commonly handled.
Promise usage
The syntax is new Promise(function(resolve, reject) { ... });
. Promise executes a function and returns resolve
on success or reject
on failure. The return
statement is ignored.
Example
By MDN web docs.
function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
});
}
Functions can be defined using Promise as shown above. The order of processing is controlled by .then
.
myAsyncFunction.then( ... );
Multiple operations can be controlled with Promise.all
.
const promiseA = () => {
return new Promise((resolve, reject) => {
...
resolve( ... );
});
};
const promiseB = () => {
return new Promise((resolve, reject) => {
...
resolve( ... );
});
};
Promise.all([promiseA, promiseB])
.then((values) => {
console.log(values[0]); // return from promiseA
console.log(values[1]); // return from promiseB
});
If all succeed, the respective values are returned. If the process fails at any Promise, the reason for the failure is returned at that point. In this case .all
is used, so the returned values are arrays, but if you don't like it, use .spread
.
async/await
An await
in the async function
can be executed after the asynchronous process is finished.
const myAsync = async () => {
const value = await promiseB;
console.log(value);
};
myAsync();
Exception handling
In Promise, you can use Promise.prototype.catch
instead of try/catch. async/await is the same because it is Promise inside.
Promise.all([promiseA, promiseB])
.then((values) => {
console.log(values[0]); // return from promiseA
console.log(values[1]); // return from promiseB
})
.catch((error) => {
console.error(error);
});
const myAsync = async () => {
const value = await promiseB.catch(() => "");
console.log(value);
};
myAsync();
Browser Support
Checking the browser implementation status on MDN web docs, Promise is defined in ECMAScript 2015 (6th Edition, ECMA-262), and IE can say goodbye to it.
The async function is defined in ECMAScript 2017 (ECMA-262), and IE is naturally not supported. It also requires a relatively new browser version. iOS Safari requires iOS 10.1 or later, so it seems to be iOS 10 or later.
The latter is not known to support Node.js, but it probably works on my environment, so it should work on 8.10.0.