1

Below code is giving me the error SyntaxError: await is only valid in async functions and the top level bodies of modules. I don't know what I am missing here.

function timeout(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function test(num) {
    return new Promise((resolve, reject) => {
        await timeout(1000);
        if (num == 11) {
            reject("error");
        }
        else {
            resolve("completed");
        }
    });
}
test(11).then((val) => { console.log(val) }).catch((err) => { console.log(err) });
Rohit Kumar
  • 65
  • 1
  • 8
  • 4
    relevant: [Is it an anti-pattern to use async/await inside of a new Promise() constructor?](https://stackoverflow.com/q/43036229) – VLAZ Mar 01 '21 at 09:01
  • The callback function inside a promise is not async so obviously you cannot use await in it. Granted it's an anti-pattern you could fix it by adding `async` keyword infront of the anonymous callback inside a promise ( `async (resolve, reject) => {}` ) – Krzysztof Krzeszewski Mar 01 '21 at 09:03
  • `(resolve, reject)` to `async (resolve, reject)` – hoangdv Mar 01 '21 at 09:05
  • Thank you very much. It resolved. So, If I am correct it checks the one level above function is async or not. – Rohit Kumar Mar 01 '21 at 09:06
  • 1
    @RohitKumar it checks *the current function*, yes. – VLAZ Mar 01 '21 at 09:07

1 Answers1

3

Because the function you're trying to use it in (the promise executor function you're passing the promise constructor) isn't an async function (and should never be). The await operator only exists in async functions. The job of the promise executor is to start the asynchronous process that the promise will report the completion of. If doing that involves using an existing promise (which would be your reason for using an async function, so you could await it), you don't use new Promise at all; you chain off the promise you already have. (More in the answers to Is it an anti-pattern to use async/await inside of a new Promise() constructor?. Spoiler: Yes, it is. :-D ) In your example, you'd just use the promise from timeout, like this:

function timeout(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}
async function test(num) {
    await timeout(1000);
    if (num == 11) {
        throw "error"; // (Best practice is to use `new Error` here)
    }
    return "completed";
}
test(11).then((val) => { console.log(val) }).catch((err) => { console.log(err) });

A couple of notes on that code:

  • To reject the promise the async function implicitly creates, you either throw or return a promise that is/will be rejected. More in my answer here: How to reject in async/await syntax?. That's what I'm doing above with throw "error";.
  • To fulfill the promise the async function implicitly creates, you return a value (return "completed" in the above). (More generally: to resolve the promise, you use return, which either fulfills it with a value or makes it follow another promise if you return one. My about that terminology in my blog post Let's talk about how to talk about promises.)
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875