1

My await for asyncCall() to finish in the inputEntriesNotOnScreen function does not work despite it being in an async function. I get this error:

Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules

What does the second part of the error mean?

function resolve1MS() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 1);
  });
}

async function asyncCall() {
  let clicked = false;
  while( !clicked){
    await resolve1MS();
    if($('.ui-menu-item').length != 0){
      $('.ui-menu-item')[0].click();
      clicked = true;
      $matrix = $("table.timesheet tbody tr");
      return {
        lastRow: $matrix.last()
      }
    }
  }
}

async function inputEntriesNotOnScreen($matrix, notFoundInInitialSearch){
  let lastRow = undefined;
  notFoundInInitialSearch.forEach(function(item, index){
    console.log(item, index);
    if( lastRow == undefined){
      lastRow = $matrix.last();
    }
    else{
      lastRow = await asyncCall();
    }
    lastRow.find('.search')[0].click();
    let $searchBar = $('.ui-autocomplete-input');multiple times
    $($searchBar[index]).val(item[0][0]);
    $searchBar[index].dispatchEvent(new Event('input'));
  });
}
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Dillon V
  • 33
  • 5
  • how are you calling `inputEntriesNotOnScreen`? – Will Jenkins Oct 18 '21 at 18:34
  • 2
    You are creating an inner function for the forEach which is not async. Replace the `forEach` with a `for` loop. – Alberto Rivera Oct 18 '21 at 18:34
  • It's referring to ES2015 Module syntax. You are technically allowed to use `await` in the top level of modules, as opposed to having to write an async function. See [the proposal that made it happen](https://github.com/tc39/proposal-top-level-await). It will be included in ES2022. – Heretic Monkey Oct 18 '21 at 18:38
  • 1
    @AlbertoRivera thank you I was confused and forgot that I was actually creating another function! – Dillon V Oct 18 '21 at 18:46

1 Answers1

1

You are creating a function to pass to your forEach which is not async.

Replacing the forEach with a standard for loop should allow you to use await as needed.

As a heads up, if you make the function in the forEach async, like forEach(async function(item, index), you will be able to use await inside the function, but all the callbacks will be ran in parallel (after reaching the await), and you won't have a way to wait for them.

https://jsfiddle.net/8nwdus0h/

For more information, you can read Using async/await with a forEach loop

Alberto Rivera
  • 3,652
  • 3
  • 19
  • 33