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/
