async / await
appeared in Node.js (from version 7.6.), I got the perception of promises as something like a temporary tool. I must say that async / await
can also be used in browser code thanks to transpilers like babel . // : ! let hn = require('@datafire/hacker_news').create(); let storyIDs = hn.getStories({storyType: 'top'}); let topStory = hn.getItem({itemID: storyIDs[0]}); console.log(`Top story: ${topStory.title} - ${topStory.url}`);
// : ! let hn = require('@datafire/hacker_news').create(); hn.getStories({storyType: 'top'}, (err, storyIDs) => { if (err) throw err; hn.getItem({itemID: storyIDs[0]}, (err, topStory) => { if (err) throw err; console.log(`Top story: ${topStory.title} - ${topStory.url}`); }) })
try / catch
will not work. let hn = require('@datafire/hacker_news').create(); Promise.resolve() .then(_ => hn.getStories({storyType: 'top'})) .then(storyIDs => hn.getItem({itemID: storyIDs[0])) .then(topStory => console.log(`Top story: ${topStory.title} - ${topStory.url}`))
Promise.resolve()
and because of all the .then()
constructs present here.async / await
construction: let hn = require('@datafire/hacker_news').create(); (async () => { let storyIDs = await hn.getStories({storyType: 'top'}); let topStory = await hn.getItem({itemID: storyIDs[0]}); console.log(`Top story: ${topStory.title} - ${topStory.url}`); })();
await
keyword is used here. In addition, we placed the code in an anonymous function, declared with the async
in order to make this code fragment better suited for further work with it.hn.getStories()
and hn.getItem()
are designed so that they return promises. When executed, the event loop is not blocked. Thanks to async / await
, for the first time in JS history, we were able to write asynchronous code using the usual declarative syntax!async / await
in your projects? If you are already working with promises, then you are ready to move to a new technology. Any function that returns a promis can be called using the await
keyword, which causes it to return the result of the promise resolution. However, if you are going to switch to async / await
from callbacks, you will first need to convert them to promises..then()
chains, switching to async / await
will not be difficult: you just need to rewrite each .then()
construct .then()
using await
..catch()
block must be replaced with standard try / catch
blocks. As you can see, finally we can use the same approach for error handling in synchronous and asynchronous contexts!await
keyword cannot be used at the top level of modules . It must be used inside functions declared with the async
. let hn = require('@datafire/hacker_news').create(); // : Promise.resolve() .then(_ => hn.getStories({storyType: 'top'})) .then(storyIDs => hn.getItem({itemID: storyIDs[0])) .then(topStory => console.log(topStory)) .catch(e => console.error(e)) // async / await: (async () => { try { let storyIDs = await hn.getStories({storyType: 'top'}); let topStory = await hn.getItem({itemID: storyIDs[0]}); console.log(topStory); } catch (e) { console.error(e); } })();
async / await
is to pre-convert callbacks into promises. Then, using the above method, the code using promises is rewritten using async / await
. You can read about how to convert callbacks into promises here .async / await
.Array.forEach
instead of the usual for
loop: const BEATLES = ['john', 'paul', 'george', 'ringo']; // for: for (let i = 0; i < BEATLES.length; ++i) { console.log(BEATLES[i]); } // Array.forEach: BEATLES.forEach(beatle => console.log(beatle))
await
the Array.forEach
method will not work properly, since it is designed to perform synchronous operations: let hn = require('@datafire/hacker_news').create(); (async () => { let storyIDs = await hn.getStories({storyType: 'top'}); storyIDs.forEach(async itemID => { let details = await hn.getItem({itemID}); console.log(details); }); console.log('done!'); // ! , getItem() . })();
forEach
runs a bunch of simultaneous asynchronous calls to getItem()
and returns immediately, without waiting for the results, so the first thing that is displayed on the screen is the string “done!”.for
loop (which will perform the operations sequentially) or the Promise.all
construction (it will perform the operations in parallel): let hn = require('@datafire/hacker_news').create(); (async () => { let storyIDs = await hn.getStories({storyType: 'top'}); // for ( ) for (let i = 0; i < storyIDs.length; ++i) { let details = await hn.getItem({itemID: storyIDs[i]}); console.log(details); } // Promise.all ( ) let detailSet = await Promise.all(storyIDs.map(itemID => hn.getItem({itemID}))); detailSet.forEach(console.log); })();
async / await
you no longer need to think about what you are writing asynchronous code. This is fine, but here lies the most dangerous trap of new technology. The fact is that with this approach, you can forget about the little things that can have a huge impact on performance. let hn = require('@datafire/hacker_news').create(); (async () => { let user1 = await hn.getUser({username: 'sama'}); let user2 = await hn.getUser({username: 'pg'}); let [more, less] = [user1, user2].sort((a, b) => b.karma - a.karma); console.log(`${more.id} has more karma (${more.karma}) than ${less.id} (${less.karma})`); })();
getUser()
call will not be executed until the first one is completed. The calls are independent, they can be executed in parallel. Therefore, below is a better solution: let hn = require('@datafire/hacker_news').create(); (async () => { let users = await Promise.all([ hn.getUser({username: 'sama'}), hn.getUser({username: 'pg'}), ]); let [more, less] = users.sort((a, b) => b.karma - a.karma); console.log(`${more.id} has more karma (${more.karma}) than ${less.id} (${less.karma})`); })();
async / await
construct has contributed to the development of asynchronous JavaScript code. The ability to describe asynchronous constructions using the same syntax as synchronous is the standard of modern programming. And the fact that now the same opportunity is available in JavaScript is a huge step forward for everyone who writes in this language.Source: https://habr.com/ru/post/339770/
All Articles