javascript - await er kun gyldig i asynkron funksjon


Jeg skrev denne koden i lib/helper.js:

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

Så prøvde jeg å bruke det i en annen fil:

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

Jeg fikk en feil:

await er kun gyldig i asynkron funksjon

Hva er problemet?

Svar #1

Feilen refererer ikke til myfunction, men til 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();


Jeg bruker anledningen til dette spørsmålet til å gi deg råd om et kjent antipattern ved bruk av await, som er: return await.


FEIL

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 as well
// 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');
})();

KORREKT

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 as well
// 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');
})();

Vær også klar over at det finnes et spesialtilfelle hvor return await er riktig og viktig: (ved bruk av try/catch)

Er det ytelsesbekymringer med `return await`?

Svar #2

For å bruke await, må konteksten der den kjøres være async av natur

Som det ble sagt, må du definere naturen til din utøvende kontekst der du er villig til å vente på en oppgave før noe som helst.

Sett bare async foran fn-deklarasjonen der din async-oppgave skal kjøre.

var start = async function(a, b) { 
  // Your async task will execute with await
  await foo()
  console.log('I will execute after foo get either resolved/rejected')
}

Forklaring:

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

Lurer på hva som skjer under panseret

await bruker promise/future/oppgave-returnerende metoder/funksjoner, og async merker en metode/funksjon som i stand til å bruke await.

Også hvis du er kjent med promises, gjør await faktisk den samme prosessen med promise/resolve. Den lager en kjede av promises og utfører din neste oppgave i resolve-tilbakekallingen.

For mer informasjon kan du referere til MDN-dokumentasjonen.

Svar #3

Da jeg fikk denne feilen, viste det seg at jeg hadde et anrop til map-funksjonen inne i min "async"-funksjon, så denne feilmeldingen refererte faktisk til at map-funksjonen ikke var merket som "async". Jeg kom rundt dette problemet ved å ta "await"-anropet ut av map-funksjonen og finne en annen måte å få ønsket oppførsel på.

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

Svar #4

Jeg hadde det samme problemet, og følgende kodeblokk ga den samme feilmeldingen:

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

Problemet er at metoden getCommits() var asynkron, men jeg ga den argumentet repo som også ble produsert av et Promise. Så jeg måtte legge til ordet async foran det slik: async(repo), og det begynte å fungere:

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

Svar #5

Hvis du skriver en Chrome-utvidelse og får denne feilen for koden din i roten, kan du fikse det ved å bruke følgende "løsning":

async function run() {
    // Your async code here
    const beers = await fetch("https://api.punkapi.com/v2/beers");
}

run();

I utgangspunktet må du pakke inn din asynkrone kode i en async function, og deretter kalle funksjonen uten å vente på den.

Svar #6

I nyere Node.js (>=14) er toppnivå await tillatt med { "type": "module" } spesifisert i package.json eller med filendelsen .mjs.

https://www.stefanjudis.com/today-i-learned/top-level-await-is-available-in-node-js-modules/

Relaterte artikler