Async/await is a new method of handling asynchronous calls in JavaScript
const requestMock = () => new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
data: {
msg: 'success',
arr: [1,2,3,4,5,6]
},
code: "200"
});
}, 1 * 1000);
});
(() => {
requestMock()
.then(res => res.data.arr)
.then(arr => {
if(arr.data.length) {
return requestMock()
.then(nextArr => {
return nextArr.map(nextEl => nextEl+5)
})
} else {
return arr.map(el => el+2)
}
}
})
.then(arr => console.log(arr));
})();
As you can see in the case above, I want to make a requestMock function on the stub to call an asynchronous operation. It is a perfect illustration of using setTimeout to make a long-running process asynchronous operation.
The promise object – that can be returned from requestMock – uses the then method. This method provides you the option to deal with the asynchronous execution, in case that requestMock ends successfully.
It is worth mentioning that the promise uses not just the then method but also the catch method. The catch method allows you to deal with the asynchronous operations which end unsuccessfully.
You will have to use requestMock() with the ‘then’ method to handle with your asynchronous operations.
(async () => {
try {
let data = [];
const arr = await requestMock();
if(arr.data.length) {
const nextArr = await requestMock();
data = nextArr.map(nextEl => nextEl+5)
} else {
data = arr.map(el => el+2)
}
console.log(data);
} catch (err) {
console.log(err);
}
})();
As you can see, in the case above I have used the async keyword, which usually means that this function is asynchronous and returns the promise. At any time you use async/await, make sure you are using the try/catch statement to handle errors.
You also ought to use await to wait for the end of requestMock and declare res to save the returned value. ‘Await’ has to be called inside async. Without await, the asynchronous function will end and it won’t wait for the effect of the asynchronous function.
The two async/await along with the promise play the identical role, but in the first case, use the ‘then’ syntax, whereas at the second case use the async/await syntax. Async/await is much more readable and more comfortable to compose. Async/await is – such as promise – non-blocking.
If you make the decision to use async/await, it is good practice to use tryCatch to handle errors. Together with promise, you need to use only catch to deal with an error. Be cautious! It’s easy to get lost using a promise when you’ve got a lot of nesting (6 levels) bracers and the statements are all returned.
With async/await you won’t have this issue. When you declare async, you may use the await keyword to make your code in a synchronous fashion. The code will appear very similar to its synchronous counterpart, but it is going to be asynchronous.
However, the significant truth is you will still need promises to compose asynchronous code.
As we have previously said, an async function returns a promise. So you can write something like that:
const makeRequest = async () => {
try {
const res = await requestMock();
return res.data.arr.map(test => test + 2);
} catch (err) {
console.log(err)
}
}
makeRequest().then(res => {
// do something
}) </code >
Therefore, you could combine the promise.all and async/await to create a lot of requests:
const makeRequest = async () => {
try {
const res = await requestMock();
return res.data.arr.map(test => test + 2);
} catch (err) {
console.log(err)
}
}
const multipleRequest = async () => {
await makreRequest() // It is not obligatory to declare the value. We can use the same function.
const [req1, res1, req3] = await Promise.all([makeRequest, makeRequest, makeRequest])
console.log([…req1, …req2, …req3 ])
}
Let us imagine you need to limit asynchronous operations in time. We typically use the async library to perform it. One of the functions in this library is mapLimit.
MapLimit provides you the opportunity to conduct asynchronous operations if you want to do a few operations at the same time however not all of them at once.
const mapLimit = async (arr, perChunk) => {
const promiseArr = arr.reduce((all,one,i) => {
const ch = Math.floor(i/perChunk);
all[ch] = [].concat((all[ch]||[]),one);
return all
}, [])
for (const promise of promiseArr) {
await Promise.all(promise.map(func => func()))
console.log('done!');
}
return 'Success!!'
}
const promiseArr = [request, request, request, request, request, request, request, request, request, request, request, request]
(async () => {
try {
const limit = 3;
await mapLimit(promiseArr, limit);
} catch (err) {
console.log(err)
}
})();
// or …
// ;(() => {
// mapLimit(datadad, 3)
.then(console.log)
.catch(console.error)
// })()
From the case above, it is possible to observe a standard request function to stub the very long background process. At this point, you are able to create the mapLimit function. In the mapLimit function, you are able to slice up an array of functions into a chunk array.
Then, you may use the for-of loop that was added in ES6 to get the elements of this array.
In the loop, it is helpful to use await Promise.all since you would like to process the requests simultaneously. That is possible because in the beginning of the function, the main array is divided into arrays of chunks functions.
Congratulations! At this point, you have the generic mapLimit function. You can use it every single time you need to process anything simultaneously!
Do you have IT recruitment needs?
NNode.js 10 was released on April 24, 2018. The publication of Node.js 10 has been a sort of breakthrough since this version permits you to use async/await, when you operate on streams.
Additionally, it is worth mentioning the ES2018 version allows the chance to perform an asynchronous iteration.
Normally, your streams look like this:
const main = inputFile => {
const readStream = fs.createReadStream(inputFile, { encoding: 'utf8' });
readStream.on('data', (line) => {
console.log(line);
});
readStream.on('end', () => {
console.log('SUCCESS!!');
});
}
Node.js 10 gives you the chance to use an asynchronous iteration to read a file asynchronously. You can iterate streams only in the event that you declare async before the function. More examples are to be found on this page: 2ality.com
const main = async inputFile => {
const readStream = fs.createReadStream(inputFile, { encoding: 'utf8' });
for await (const line of readStream) {
console.log(line);
}
console.log('SUCCESS!!');
}
You see? Everything is readable and comprehensible. In this instance, we used the for-await-of loop to iterate. This operation is possible thanks to the Symbol.asyncIterator.
‘Async Iterators` are pretty similar to regular iterators because they implement 3 methods: the next method moves to the next item (the remaining part of the bullet list) and finally a return or a throw method.
There are some discrepancies between an ‘async iterator’ and a traditional ‘iterator’. Rather than returning a plain object { value, done }, an async iterator returns a promise which is the counterpart of { value, done }.
In the same way, an async iterable is an object with a Symbol.asyncIterator function that returns an asynchronous iterator. It allows you to alter the syntax of ‘for…of’ to an asynchronous for await…of.
All these are implemented in current versions of Node.js, and also you can use them by using the – harmony-async-iteration flag.
You can write code both in an asynchronous fashion and an instinctive manner. Async/await is a syntax that was added in ES8 (ECMAScript 2017) of the JavaScript version. It is supported by all browsers. Node.js developers can use this syntax from the Node.js 8 version.
As you can see, the async/await syntax is not that complex. Are you still asking yourself the question “Async/await – how exactly does it work?”. Do not worry.
It is merely one more method of coping with the promise object, and thanks to this you are now able to write code a whole lot more synchronously and intuitively. It is also important to keep in mind that the ‘Async’ function returns a promise but ‘await’ can only be used within the async.
Lastly, do not forget that you are not left alone with your doubts — if you find something unclear, seek answers on portals for developers, for example Github! Also, feel free to reach us at DevsData anytime.
Frequently asked questions (FAQ)
DevsData – a premium technology partner
DevsData is a boutique tech recruitment and software agency. Develop your software project with veteran engineers or scale up an in-house tech team with developers with relevant industry experience.
Free consultation with a software expert
🎧 Schedule a meeting
“DevsData LLC is truly exceptional – their backend developers are some of the best I’ve ever worked with.”
Nicholas Johnson
Mentor at YC,
Ex-Tesla engineer,
Serial entrepreneur
Categories: Big data, data analytics and AI | Software and technology | IT recruitment blog | IT in Poland | Content hub (blog)
“I interviewed about a dozen different firms. DevsData LLC is truly exceptional – their backend developers are some of the best I’ve ever worked with. I’ve worked with a lot of very well-qualified developers, locally in San Francisco, and remotely, so that is not a compliment I offer lightly. I appreciate their depth of knowledge and their ability to get things done quickly. “
Nicholas Johnson
CEO of Orange Charger LLC,
Ex-Tesla Engineer,
Mentor at YCombinator