The problem

The original question is from @Jose.

You can modify the following aa() function to print the want-value with console.log() after a second

function aa() {
    setTimeout(function() {
        return "want-value";
    }, 1000);
}

However, there are additional requirements:

  1. aa()Functions can be changed at will, but not at allconsole.log()
  2. performconsole.log()It can’t be in the statementsetTimeoutThe parcel

answer

Maybe it’s an interview question. Whatever. The main purpose of the problem is to examine the processing of the result of the execution of an asynchronous call. Since it is an asynchronous call, it is impossible to wait for an asynchronous result synchronously, and the result must be asynchronous

SetTimeout () is often used to simulate asynchronous operations. Originally, asynchrony was used by callbacks to notify (invoke) the handler to process the result

function aa(callback) { setTimeout(function() { if (typeof callback === "function") { callback("want-value"); }}, 1000); } aa(function(v) { console.log(v); });

However, when used in a slightly larger asynchronous application, callbacks tend to appear multiple layers of nesting, so some “flattening” of them is proposed later. This part can refer to the “flattening” of asynchronous calls. Promise was, of course, a very popular approach, and was eventually adopted by ES6. Use Promise to do the following:

function aa() {
    return new Promise(resolve => {
        setTimeout(function() {
            resolve("want-value");
        }, 1000);
    });
}

aa().then(v => console.log(v));

In this case, it’s pretty much the same as the previous callback example. However, it would lead to the currently more recommended method async/await, which is supported from ES2017:

function aa() {
    return new Promise(resolve => {
        setTimeout(function() {
            resolve("want-value");
        }, 1000);
    });
}

async function main() {
    const v = await aa();
    console.log(v);
}

main();

The definition of aa() is the same as in the Promise method, but when called, we use await, wait asynchronously, wait for the asynchronous result, and then use console.log() to handle it.

The important thing to note here is that await can only be used within the async method, so to use await you must define an async main method and call it at global scope. Since the main method is asynchronous (declared async), if there are other statements after the main() call, such as console.log(“hello”), then this sentence will be executed first.

The async/await syntax allows asynchronous calls to be written like synchronous code, avoiding logical jumps while writing the code and making it easier to write. (See: From Hell to Heaven, Node callback to async/await transition)

Of course, defining main() and then calling main() can be wrapped in IIFE,

(async () => { const v = await aa(); console.log(v); }) ();