javascript – await is only valid in async function-ThrowExceptions

Exception or error:

I wrote this code in lib/helper.js

var myfunction = async function(x,y) {
   ....
   reutrn [variableA, variableB]
}
exports.myfunction = myfunction;

and then I tried to use it in another file

 var helper = require('./helper.js');   
 var start = function(a,b){
     ....
     const result = await helper.myfunction('test','test');
 }
 exports.start = start;

I got an error

“await is only valid in async function”

What is the issue?

How to solve:

The error is not refering to myfunction but to start.

async function start() {
   ....

   const result = await helper.myfunction('test', 'test');
}

// My function
const myfunction = async function(x, y) {
  return [
    x,
    y,
  ];
}

// Start function
const start = async function(a, b) {
  const result = await myfunction('test', 'test');
  
  console.log(result);
}

// Call start
start();


I use the opportunity of this question to advise you about an known anti pattern using await which is : return await.


WRONG

async function myfunction() {
  console.log('Inside of myfunction');
}

// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later

// useless async here
async function start() {
  // useless await here
  return await myfunction();
}

// Call start
(async() => {
  console.log('before start');

  await start();
  
  console.log('after start');
})();

CORRECT

async function myfunction() {
  console.log('Inside of myfunction');
}

// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later

// Also point that we don't use async keyword on the function because
// we can simply returns the promise returned by myfunction
function start() {
  return myfunction();
}

// Call start
(async() => {
  console.log('before start');

  await start();
  
  console.log('after start');
})();

###

When I got this error, it turned out I had a call to the map function inside my “async” function, so this error message was actually referring to the map function not being marked as “async”. I got around this issue by taking the “await” call out of the map function and coming up with some other way of getting the expected behavior.

var myfunction = async function(x,y) {
    ....
    someArray.map(someVariable => { // <- This was the function giving the error
        return await someFunction(someVariable);
    });
}

###

The real issue is you need to understand how async/await works here. The error is in your start function().

You need to define a function as an async function to use await as await consumes promise / future / task-returning methods / functions and async marks a method / function as capable of using await. await is actually doing the same process of promise / resolve and as the function is async other task is processing in a parallel way.

For more info you can refer to MDN DOCS.

async function foo(){
  let myAsyncCall = await .... ('/endpoint') // hitting on some api
  console.log(myAsyncCall) // myAsyncCall will log out whenever the request get resolved
}

foo()

###

The current implementation of async / await only supports the await keyword inside of async functions Change your start function signature so you can use await inside start.

 var start = async function(a, b) {

 }

For those interested, the proposal for top-level await is currently in Stage 2: https://github.com/tc39/proposal-top-level-await

###

I had the same problem and the following block of code was giving the same error message:

repositories.forEach( repo => {
        const commits = await getCommits(repo);
        displayCommit(commits);
});

The problem is that the method getCommits() was async but I was passing it the argument repo which was also produced by a Promise. So, I had to add the word async to it like this: async(repo) and it started working:

repositories.forEach( async(repo) => {
        const commits = await getCommits(repo);
        displayCommit(commits);
});

###

“await is only valid in async function”

But why? ‘await’ explicitly turns an async call into a synchronous call, and therefore the caller cannot be async (or asyncable) – at least, not because of the call being made at ‘await’.

###

Yes, await / async was a great concept, but the implementation is completely broken.

For whatever reason, the await keyword has been implemented such that it can only be used within an async method. This is in fact a bug, though you will not see it referred to as such anywhere but right here. The fix for this bug would be to implement the await keyword such that it can only be used TO CALL an async function, regardless of whether the calling function is itself synchronous or asynchronous.

Due to this bug, if you use await to call a real asynchronous function somewhere in your code, then ALL of your functions must be marked as async and ALL of your function calls must use await.

This essentially means that you must add the overhead of promises to all of the functions in your entire application, most of which are not and never will be asynchronous.

If you actually think about it, using await in a function should require the function containing the await keyword TO NOT BE ASYNC – this is because the await keyword is going to pause processing in the function where the await keyword is found. If processing in that function is paused, then it is definitely NOT asynchronous.

So, to the developers of javascript and ECMAScript – please fix the await/async implementation as follows…

  • await can only be used to CALL async functions.
  • await can appear in any kind of function, synchronous or asynchronous.
  • Change the error message from “await is only valid in async function” to “await can only be used to call async functions”.

Leave a Reply

Your email address will not be published. Required fields are marked *