最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Nodejs why is await only restricted to async functions? - Stack Overflow

programmeradmin2浏览0评论

Possible duplicate of await is only valid in async function.

I am new to NodeJS and I found the concept of async-await a bit confusing. After some reading and muddling around, this is my understanding of the same.

Suppose, I have a function sum like this.

function sum(a, b) {
  // print the numbers
  for (var i = 0; i < 100000; i++) {
    console.log(i);
  }
  // settimeout
  new Promise (resolve => {
    setTimeout(resolve, 1000);
  });
  return a+b;
}

function main() {
  let a = sum(5,2);
  console.log(a);
}

main();

It allocates a new thread for the timer and continues with the normal flow. It prints all the numbers first, returns a 7 and then waits for 1 second before exiting.

But now I want to execute the lines in the order they are written. It makes sense to put an await keyword before the timer Promise.

async function sum(a, b) {
  // print the numbers
  for (var i = 0; i < 100000; i++) {
    console.log(i);
  }
  // settimeout
  await new Promise (resolve => {
    setTimeout(resolve, 1000);
  });
  return a+b;
}

Issue 1: Here, I don't understand the obligation to put async to use await. Only putting async just makes the function return a Promise instead of a value. the flow is unchanged. It still prints all the number before printing 7.

Issue 2: I think the word async before a function misleads into thinking that the function calls would be asynchronous, though they are not. Any clarification with respect to design?

Issue 3:

  • In NodeJS, there is no concept of synchronous or asynchronous function call unless we have some blocking function like timer, remote requests and IO operations. That's where the concept of async-await es into picture. Otherwise, it's just a single thread even if the program has Promises.
  • Putting async besides a function just makes it return a Promise instead of a value. It does not alter the program flow. Perhaps, it just puts some additional machinery to handle await (if any) just a guess!!.
  • async does not necessarily make any function (or its call) asynchronous. Call to function having async keyword will still be synchronous unless it contains another Promise that keeps it waiting. That's where await es in.

Is my whole understading correct?

Possible duplicate of await is only valid in async function.

I am new to NodeJS and I found the concept of async-await a bit confusing. After some reading and muddling around, this is my understanding of the same.

Suppose, I have a function sum like this.

function sum(a, b) {
  // print the numbers
  for (var i = 0; i < 100000; i++) {
    console.log(i);
  }
  // settimeout
  new Promise (resolve => {
    setTimeout(resolve, 1000);
  });
  return a+b;
}

function main() {
  let a = sum(5,2);
  console.log(a);
}

main();

It allocates a new thread for the timer and continues with the normal flow. It prints all the numbers first, returns a 7 and then waits for 1 second before exiting.

But now I want to execute the lines in the order they are written. It makes sense to put an await keyword before the timer Promise.

async function sum(a, b) {
  // print the numbers
  for (var i = 0; i < 100000; i++) {
    console.log(i);
  }
  // settimeout
  await new Promise (resolve => {
    setTimeout(resolve, 1000);
  });
  return a+b;
}

Issue 1: Here, I don't understand the obligation to put async to use await. Only putting async just makes the function return a Promise instead of a value. the flow is unchanged. It still prints all the number before printing 7.

Issue 2: I think the word async before a function misleads into thinking that the function calls would be asynchronous, though they are not. Any clarification with respect to design?

Issue 3:

  • In NodeJS, there is no concept of synchronous or asynchronous function call unless we have some blocking function like timer, remote requests and IO operations. That's where the concept of async-await es into picture. Otherwise, it's just a single thread even if the program has Promises.
  • Putting async besides a function just makes it return a Promise instead of a value. It does not alter the program flow. Perhaps, it just puts some additional machinery to handle await (if any) just a guess!!.
  • async does not necessarily make any function (or its call) asynchronous. Call to function having async keyword will still be synchronous unless it contains another Promise that keeps it waiting. That's where await es in.

Is my whole understading correct?

Share Improve this question asked Nov 26, 2018 at 6:33 ShashwatShashwat 2,6687 gold badges42 silver badges58 bronze badges 13
  • 3 Couple of thoughts: In order for a function to be able to await another promise, it itself needs to return a promise. Getting this implicitly through async seems useful. Also, the fact that the function is "marked" as async helps the parser (var await = ...; is valid in non-async functions, but not in async functions). Lastly, async/await exists in various languages. Not sure about the technical details there, but if it's pretty easy to learn that async means Promise. How exactly the function is executed is irrelevant at that point. – Felix Kling Commented Nov 26, 2018 at 6:43
  • 2 In order for a function to be able to await another promise, it itself needs to return a promise. I guess this is my question. Why is that? – Shashwat Commented Nov 26, 2018 at 6:49
  • 2 A promise is resolved at some unknown point in time in the future. awaiting a promise means getting its resolved value and do something with it. That means that function that awaits a promise can only return at some unknown point in time in the future. And this, in turn, is done by returning a promise now (and resolving it in the future). – Felix Kling Commented Nov 26, 2018 at 6:55
  • @Shashwat It doesn't though, a function can return a value, nothing at all, or another promise. Felix Kling has good explanation for the why. – Drew Reese Commented Nov 26, 2018 at 6:56
  • 1 It would be pretty horrible if you could use await anywhere and the function wouldn't return a promise – Bergi Commented Nov 26, 2018 at 7:28
 |  Show 8 more ments

3 Answers 3

Reset to default 5

Your function is not a great example, because the return value is not in any way connected to the await result. Because of this, the use of Promise is irrelevant, as the code could be rewritten without it. Let's change your function a bit, so that it actually generates the result inside the promise:

function sumLater(a, b) {
  return new Promise(resolve => {
    setTimeout(() => resolve(a+b), 1000);
  });
}

async function sum(a, b) {
  // print the numbers
  for (let i = 0; i < 100000; i++) {
    console.log(i);
  }
  // settimeout
  let result = await sumLater(a, b);
  // using the awaited result
  console.log("The awaited result is", result);
  return result;
}

async significantly changes the way the function is executed internally. For one thing, no function using a promise can ever return a value that is generated inside the promise. In the same way, no function that contains await can return anything generated from await onwards without it being wrapped in a promise. The reason for this is the lack of time travel in current putational architectures. If a function could now return a result of an operation that will plete two hours later, it would be a rather impressive breakthrough.

async is as much a signal to the JavaScript engine that the function will be executed in this special way, as well as to human code readers that it returns a Promise, not the returned value (unless the returned value was already a promise in the first place, and did not need wrapping).

Most of your issues are due to a terminological confusion. Don't get hung up on literal meaning of the terminology. Nothing in JavaScript (except Web Workers) is simultaneous, and at the first glance simultaneous and synchronous should be synonyms. In JavaScript, synchronous means "executes entirely within the same task", and asynchronous means "causes a new task to be placed on the execution stack", more or less, as far as I see it. Seen from this angle, async does mean that the function will be asynchronous, for the meaning "asynchronous" has in JavaScript.

Just making a return promise using async-await or promise doesn't really make a function asynchronous. async-await or promise are to used handle real asynchronous functions of Javascript.

Asynchronous functions can only be setTimeout, setInterval, requestAnimationFrame and other functions.
For more over asynchronous function check this post How to Create asynchronous function in javascript?.

Will explain this using two examples one with async-await and other with promise and what's different between them:

  1. promise:

    function main() {
        return new Promise( resolve => {
           console.log(1);
           resolve(true);
        });
    }

    main()
    .then( result => {    // result will have whatever main promise will resolve.
        console.log(2);
    });

    console.log(3);

If using promise or returning promise would make a function asynchronous then output order would be

3
1
2

However just returning a promise doesn't make a function asynchronous thus output is

1
3
// Asynchronous happen here
2

Now why 2 after 3? as only Javascript asynchronous function can be asynchronous and goes into callstack and then in event-queue, then callback function of .then( function() {}) is true asynchronous function of javascript and thus this behavior. Note calling main() returns a promise function. This will be used in difference between promise and async-await.

  1. async-await

    async function main() {
        console.log(1);
        return true;
    }

    main()
    .then( result => {  // Result have whatever main function return.
        console.log(2);
    });
    
    console.log(3);

Similar to above this will also print

1
3
// Asynchronous happen here
2

What's the difference between async-await and promise? async-await can only handle promise using await and any asynchronous function which doesn't return promise and in place uses a callback function, like setTimeout, setInterval, request.js, https.js functions etc., can't be handled with async-await. To handle such function we can only use Promise, as Promise uses callback function thus ability to handle any asynchronous function:

function timeout() {
    return new Promise( (resolve, reject) => {
        console.log(1);
        setTimeout( function() {
            console.log(2);
            resolve(true);
        }, 1000);
    });
}

async function main() {
    console.log(3);
    let result = await timeout();
    console.log(4);
    return result;
}

main()
.then( result => {
    console.log(5);
});

console.log(6);

As expected on reaching asynchronous function setTimeout callback function was pushed to event-queue and continue processing, again on await is asynchronous (not a function but behave as .then()) pushed on event-queue. and rest all continue thus output is:

3
1
6
// asynchronous happens here
2
4
5

Last example to explain in detail about await, removed use of setTimeout from last example:

function timeout() {
    return new Promise( (resolve, reject) => {
        console.log(1);
        console.log(2);
        resolve(true);
    });
}

async function main() {
    console.log(3);
    let result = await timeout();
    console.log(4);
    return result;
}

main()
.then( result => {
    console.log(5);
});

console.log(6);

As expected output:

3
1
2
6
// Asynchronous await here
4
5

As async-await wait for promise to resolve thus can't be used with callback asynchronous function, else async-await make code more clear and nice and also reduce callback chains of .then(). Promise is must use to make callback asynchronous functions and prevent callback hell.

It's still javascript, which means it's all still running on a single thread. The await keyword pauses the execution of the async function AT that line until that line resolves, possibly with a value, at which point execution continues within that function. The reason you see all the numbers print first both times is because that code is before any asynchronous calls. The execution probably seems the same in both your examples since printing 100000 logs takes significantly longer than the second it takes for the promise to resolve.

发布评论

评论列表(0)

  1. 暂无评论