Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ES 2017: async function vs AsyncFunction(object) vs async function expression

I was just reading about async functions and came across some similar features of ES2017. It has created a lot of confusion, I wanted to just ask:

  1. What is the difference between async function, AsyncFunction (which is used to create an async function), and an async fuction expression (which is what I think just another async function)?
  2. When should I use one format over another?

Highlights on the quirks and performance of each would be appreciated!

like image 782
Syed Huzaifa Hassan Avatar asked Feb 16 '17 01:02

Syed Huzaifa Hassan


People also ask

What are the differences between an async function and a regular function?

The word “async” before a function means one simple thing: a function always returns a promise. Other values are wrapped in a resolved promise automatically. So, async ensures that the function returns a promise, and wraps non-promises in it.

Why promise executor functions should not be async?

The executor function can also be an async function . However, this is usually a mistake, for a few reasons: If an async executor function throws an error, the error will be lost and won't cause the newly-constructed Promise to reject. This could make it difficult to debug and handle some errors.

Should I use await or then?

Async/await and then() are very similar. The difference is that in an async function, JavaScript will pause the function execution until the promise settles. With then() , the rest of the function will continue to execute but JavaScript won't execute the . then() callback until the promise settles.

Is async await better than promises?

Async/Await is used to work with promises in asynchronous functions. It is basically syntactic sugar for promises. It is just a wrapper to restyle code and make promises easier to read and use. It makes asynchronous code look more like synchronous/procedural code, which is easier to understand.


1 Answers

There are four ways to create a function in Javascript. There are also four ways to create an asynchronous function in Javascript, and they are precise mirrors of each other.

To demonstrate how this works, I'm using a simple sleep function, declared globally:

function sleep(time) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve();
        }, time);
    });
}

Function declarations

function speak() { return 'Hi'; }
async function speak() { await sleep(1000); return 'Hi'; }

This is the simplest way to declare a function. It can be declared once and is hoisted to the top of the current function scope.

Function declarations and asynchronous function declarations are exactly identical, except that the async function always returns a promise and allows you to use await.

Function expressions

let speak = function() { return 'Hi'; } // anonymous function expression
let speak = function speakFn() { return 'Hi'; } // named function expression

let speak = async function() { await sleep(1000); return 'Hi'; } // anonymous asynchronous function expression
let speak = async function speakFn() { await sleep(1000); return 'Hi'; } // named asynchronous function expression

Function expressions look very much like function declarations. They are not, however, hoisted to the top of the function scope. They can be redefined as many times as you like. They can be defined inline. They can either be anonymous or named: if they are named, then the name refers to the function within the scope of that function.

Function expressions and asynchronous function expressions are exactly identical, except that the async function always returns a promise and allows you to use await.

Arrow functions

let speak = word => 'Hi ' + word; // one parameter
let speak = (word1, word2) => 'Hi ' + word1 + word2; // multiple parameters

let speak = async word => { await sleep(1000); return 'Hi ' + word; } // one parameter
let speak = async (word1, word2) => { await sleep(1000); return 'Hi ' + word1 + word2; } // multiple parameters

Arrow functions are a quick and short way to define a function, introduced in ES2015 (ES6). They are in most ways equivalent to function expressions, except that they are always anonymous and the value of this is always lexically bound, i.e. inherited from the outer scope.

Arrow functions and asynchronous arrow functions are exactly identical, except that the async function always returns a promise and allows you to use await. (They are slightly different in the statements above because the asynchronous functions each have more than one statement within them. This means that the statements need to be enclosed in a block {} and the return needs to be explicit. This is also true of normal arrow functions that are more than one statement long.)

Function constructors

let speak = new Function('word', 'return "Hi " + word;');
let speak = new AsyncFunction('word', 'await sleep(1000); return "Hi " + word;')

Function constructors allow you to define a function dynamically by using strings. Note that they are always run in the global scope and have no access to the scope in which they were defined. They are only useful in a very small set of circumstances. I personally can't see how an asynchronous function constructor would ever be a useful thing. The writers of ES2017 agree with me, as AsyncFunction is not a global object and must be obtained first with const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor.

Functions created with the function constructor and functions created with the anonymous function constructor are exactly identical, except that the async function always returns a promise and allows you to use await. (But you'd already guessed that, right?)

like image 181
lonesomeday Avatar answered Sep 23 '22 01:09

lonesomeday