📜 ⬆️ ⬇️

Asynchronous functions 101

One of the main advantages of JavaScript is that everything is asynchronous. For the most part, different parts of your code do not affect the execution of others.


doALongThing(() => console.log("I will be logged second!")); console.log("I will be logged first!"); 

Unfortunately, this is also one of the major drawbacks of javascript. The task of executing synchronous code becomes more complicated, since by default everything is asynchronous.
The first solution was kolbeki. If part of our code depends on some result, we should have inserted our code -


 doSomething((response) => { doSomethingElse(response,(secondResponse) => { doAThirdThing(secondResponse); }); }) 

Nested callbacks in callbacks, as we know, become unsuitable. Thus, Promises were created. They allowed us to work with synchronous code in a cleaner and flatter way.


 doSomething() .then((response) => doSomethingElse(response)); .then((secondResponse) => doAThirdThing(secondResponse)); // Even cleaner doSomething().then(doSomethingElse).then(doAThirdThing); 

Like everyone else, promises are not perfect either. Thus, within the framework of the ES2017 specification, another method has been defined for working with synchronous code: Asynchronous functions. This allows us to write asynchronous code as if it were synchronous.


Creating an asynchronous function


An asynchronous function is defined by an asynchronous function expression. The basic function is as follows:


 async function foo() { const value = await somePromise(); return value; } 

We define a function as asynchronous using async . This keyword can be used with any function declaration syntax -


 // Basic function async function foo() { … } // Arrow function const foo = async () => { … } // Class methods class Bar { async foo() { … } } 

Once we have defined the function as asynchronous, we can use the await keyword.
This keyword is placed before the promise call, it pauses the execution of the function until the promise is executed or rejected.


Error processing


Error handling in asynchronous functions is performed using try and catch blocks.
The first block (try) allows us to try the action. The second block (catch), is called if the action is not performed. It takes one parameter containing any error.


 async function foo() { try { const value = await somePromise(); return value; } catch (err) { console.log("Oops, there was an error :("); } } 

Using Asynchronous Functions


Asynchronous functions are not a replacement for promises. They are identical in nature. Thus, the asynchronous function waits for the fulfillment of a promise and always returns a promise.


The promis returned by the asynchronous function will be resolved with any value returned by the function.


 async function foo() { await somePromise(); return 'success!' } foo().then((res) => console.log(res)) // 'success!' 

If an error is thrown, the promise will be rejected with this error.


 async function foo() { await somePromise(); throw Error('oops!') } foo() .then((res) => console.log(res)) .catch((err) => console.log(err)) // 'oops!' 

Performing Asynchronous Functions in Parallel


With promises, we can fulfill several promises in parallel using the Promise.all (). method Promise.all ().


 function pause500ms() { return new Promise((res) => setTimeout(res, 500)); } const promise1 = pause500ms(); const promise2 = pause500ms(); Promise.all([promise1, promise2]).then(() => { console.log("I will be logged after 500ms"); }); 

With asynchronous functions, we need to work a little to get the same effect. If we simply enumerate every function that is waiting in the queue, they will be executed sequentially, since await suspends the execution of the rest of the function.


 async function inSequence() { await pause500ms(); await pause500ms(); console.log("I will be logged after 1000ms"); } 

It will take 1000 ms, since the second wait will not start until the first one is completed. To get around this, we need to reference functions like this:


 async function inParallel() { const await1 = await pause500ms(); const await2 = await pause500ms(); await await1; await await2; console.log("I will be logged after 500ms"); } 

Now it takes only 500 ms, because both functions of pause500ms () are executed simultaneously.


Promises or Asynchronous Functions?


As I already mentioned, asynchronous functions do not replace promises. They are identical in nature. Asynchronous functions provide an alternative, and in some cases, a better way to work with promise-based functions. But they still use and produce promises.


As the promise is returned, the asynchronous function may be called by another asynchronous function or by promis. We can mix and match, depending on which syntax is best suited for each case.


 function baz() { return new Promise((res) => setTimeout(res, 1000)); } async function foo() { await baz(); return 'foo complete!'; } async function bar() { const value = await foo(); console.log(value); return 'bar complete!'; } bar().then((value) => console.log(value)); 

The following happens:



Support


As of this writing, asynchronous functions and promises are available in current versions of all major browsers, with the exception of Internet Explorer and Opera Mini.




')

Source: https://habr.com/ru/post/326442/


All Articles