await yalnızca eşzamansız işlevde geçerlidir


130

Bu kodu şuraya yazdım lib/helper.js

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

ve sonra onu başka bir dosyada kullanmayı denedim

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

Bir hata aldım

"await yalnızca eşzamansız işlevde geçerlidir"

Sorun ne?


1
Sorun şu ki await, yalnızca bir asyncişlevin içinde kullanılabilir . Yani, awaitbir işlevi eşzamansız hale getirir, bu nedenle bu şekilde bildirilmesi gerekir.
Sivri

Mevcut hata nedir?
acdcjunior

hala aynı, SyntaxError: await yalnızca eşzamansız işlevde geçerlidir
j.doe

Kodunuz hakkında daha fazla bağlam paylaşmanız gerekir.
Ele

Yanıtlar:


161

Hata, atıfta bulunmaktan myfunctionziyade 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();



Ben kullanarak bilinen anti deseni hakkında bilgi vermekten Bu sorunun fırsatı kullanmak awaithangi: return await.


YANLIŞ

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


DOĞRU

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


Ayrıca, return awaitdoğru ve önemli olan özel bir durum olduğunu bilin : (dene / yakala kullanarak)

"Dönüş bekliyor" ile ilgili performans endişeleri var mı?


Ama bu çalışmıyor, kodumu güncelledim. Hala aynı hatayı alıyorum
j.doe

@ j.doe Bir pasaj ekledim
Grégory NEUT

2
Teşekkürler, sorunumu buldum. Bunu bir geri arama içinde yapmaya çalışıyordum, start () işlevi. Çözüm şuydu: const start = async function (a, b) {task.get (options, async function (error, result1) {const result = await myfunction ('test', 'test');
j.doe

Düğümün tek iş parçacıklı olduğunu düşünürsek. Dakika başına talebi azaltmaz ve ayrıca doldurma talepleri arasındaki gecikmeyi arttırmaz.
Rishabh Dhiman

1
"DOĞRU" örneğinde, startbir asyncişlev olarak bildirmenin gerekli olmadığını belirtmekte fayda var (bazıları daha açık olmak için zaten bunu yapmayı
seçecek olsa da

11

Bu hatayı aldığımda, "eşzamansız" işlevimin içindeki eşleme işlevine bir çağrı olduğu ortaya çıktı, bu nedenle bu hata iletisi aslında eşleme işlevinin "eşzamansız" olarak işaretlenmemiş olduğunu gösteriyordu. Harita işlevinden "bekle" çağrısını alarak ve beklenen davranışı elde etmenin başka bir yolunu bularak bu sorunu aştım.

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

2
Benim için sorun buydu. Harita işlevini bir for döngüsü ile değiştirdim, bu benim için kolay bir çözümdü. Ancak, kodunuza bağlı olarak bu çözüm sizin için çalışmayabilir.
Thomas

6
Bilginize şunu da yapabilirsinizsomeArray.map(async (someVariable) => { return await someFunction(someVariable)})
ptim

1
awaitÇünkü Kodunuzdaki, yanıltıcı Array.mapbir asenkron fonksiyonu olarak işlev idare olmayacaktır. Tamamen açık olmak gerekirse, mapişlev tamamlandıktan sonra someFunctionhepsi beklemede olacaktır. İşlevlerin bitmesini gerçekten beklemek istiyorsanız şunu yazmalısınız: await Promise.all(someArray.map(someVariable => someFunction(someVariable)))veya await Promise.all(someArray.map(someFunction))).
Grégory NEUT

9

Kullanmak için await, yürütme bağlamının asyncdoğada olması gerekir

Dediği gibi, her şeyden önce bir göreve executing contextistekli olduğunuz yerinizin doğasını tanımlamanız gerekir await.

Sadece görevinizin yürütüleceği bildirimin asyncönüne koyun .fnasync

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')
}

Açıklama:

Sorunuzda , doğası gereği olan ve paralel olarak çalışacak methodolanı ithal ediyorsunuz asynchronous. Ancak, bu asyncyöntemi yürütmeye çalıştığınız yer , kullanmak execution contextiçin tanımlamanız gereken farklı bir yerdedir .asyncawait

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

Kaputun altında neler olduğunu merak ediyorum

awaitvaat / gelecek / görev döndürme yöntemlerini / işlevlerini tüketir ve asyncbir yöntemi / işlevi await kullanabilecek şekilde işaretler.

Ayrıca aşina iseniz promises, awaitaslında söz / kararlılığının aynı işlemi yapıyor. Bir söz zinciri oluşturmak ve resolvegeri aramada bir sonraki görevi yerine getirmek .

Daha fazla bilgi için başvurabilirsiniz MDN DOCS'a .


Başlangıç ​​işlevinde zaman uyumsuz olsa bile hatayı alıyorum
j.doe

Bu hatayı nerede kaçırdığınızdan ve aldığınızdan emin değilim, bu hatayı çözmek için böyle karmaşık bir açıklama yok.
Satyam Pathak

bu doğru bir cevap ve aslında altı çizili nedeni açıkladı. yukarı oy verildi.
linehrr

3

Mevcut uygulama async/ awaityalnızca destekler awaitanahtar kelime içindeki asyncfonksiyonları sizin değiştirin startkullanabilirsiniz böylece fonksiyon imza awaitiçeride start.

 var start = async function(a, b) {

 }

İlgilenenler için, üst düzey teklif awaitşu anda Aşama 2'de: https://github.com/tc39/proposal-top-level-await


1
Ne yazık ki, bunun temelde anlamı, tüm kod tabanınız boyunca TÜM işlevlerinizi eşzamansız hale getirmek zorunda kalacağınızdır. Çünkü await'i kullanmak istiyorsanız, bunu eşzamansız bir işlevde yapmanız gerekir, bu da onu çağıran işlevde bu işlevin yanıtını beklemeniz gerektiği anlamına gelir - yine, bu TÜM işlevlerinizin eşzamansız hale gelmesi gerektiği anlamına gelir. Bana göre bu, bekleme zaman uyumsuzluğunun kullanıma hazır olmadığı anlamına geliyor. Await'i bir eşzamansız yöntemi çağırmak için kullanabildiğiniz zaman, geçerli işlevin eşzamanlı veya eşzamansız olmasına bakılmaksızın, bu durumda birincil süre için hazır olacaktır.
Rodney P. Barbati

1
Dolaylama herhangi bir düzeyinde aracılığıyla harici işlem şırasının sonuçlarına bağlıdır ve her fonksiyon gerektiğidir ile tanımlanabilir asyncolduğunu - tüm nokta arasında async.
Gershom

Şu anda --experimental-repl-awaitseçeneğini kullanarak düğüm çoğaltmasında kullanabilirsiniz .
lodz

3

Aynı sorunu yaşadım ve aşağıdaki kod bloğu aynı hata mesajını veriyordu:

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

Sorun, getCommits () yönteminin zaman uyumsuz olmasıydı, ancak ben ona yine bir Promise tarafından üretilen argüman deposunu geçiriyordum. Bu yüzden, ona async kelimesini şu şekilde eklemem gerekiyordu: async (repo) ve çalışmaya başladı:

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

0

async / await, vaadi yerine getirme mekanizmasıdır, bunu yapmanın iki yolu

functionWhichReturnsPromise()
            .then(result => {
                console.log(result);
            })
            .cathc(err => {
                console.log(result);

            });

veya ilk önce sözün tam olarak doldurulmasını beklemek için beklemeyi kullanabiliriz, bu da reddedildiği veya çözüldüğü anlamına gelir.

Kullandığımız isteyip istemediğim bekliyoruz bir işlev içinde (yerine getirmek için bir söz bekliyor), biz uyumsuz fulfiled için bir söz bekliyor çünkü konteyner işlevi bir zaman uyumsuz işlevi olması gerektiğini zorunludur || mantıklı değil mi?

async function getRecipesAw(){
            const IDs = await getIds; // returns promise
            const recipe = await getRecipe(IDs[2]); // returns promise
            return recipe; // returning a promise
        }

        getRecipesAw().then(result=>{
            console.log(result);
        }).catch(error=>{
            console.log(error);
        });

-2

"await yalnızca eşzamansız işlevde geçerlidir"

Ama neden? "await", eşzamansız bir aramayı açık bir şekilde eşzamanlı aramaya dönüştürür ve bu nedenle, arayan kişi eşzamansız (veya eşzamansız) olamaz - en azından, "bekleme" sırasında yapılan çağrı nedeniyle değil.


1
Aslında, await sonuçları beklemez - hemen bir söz verir. Bu tam olarak anlatmaya çalıştığım şeydi. Eğer await gerçekten beklediyse ve kontrolü arayana geri vermediyse, bir await anahtar sözcüğü içeren herhangi bir işlev, tam anlamıyla eşzamansız olarak işaretlenemezdi. Ancak bunun yerine, await içeren veya sonunda await içeren bir işlevi çağıran bir işlevi çağıran herhangi bir işlevin asenkron olması gerekir. Temel olarak, bir kez bile bekle çağrısı yaparsanız, tüm işlevleriniz eşzamansız olarak işaretlenmelidir.
Rodney P. Barbati

-5

Evet, await / async harika bir konseptti, ancak uygulama tamamen bozuk.

Her ne sebeple olursa olsun, await anahtar sözcüğü, yalnızca zaman uyumsuz bir yöntem içinde kullanılabilecek şekilde uygulanmıştır. Bu aslında bir hatadır, ancak buradan başka hiçbir yerde böyle anıldığını görmeyeceksiniz. Bu hatanın düzeltmesi, await anahtar sözcüğünü, çağıran işlevin kendisi eşzamanlı veya eşzamansız olup olmadığına bakılmaksızın, yalnızca zaman uyumsuz bir işlevi ÇAĞIRMAK İÇİN kullanılabilecek şekilde uygulamak olacaktır.

Bu hata nedeniyle, kodunuzun herhangi bir yerinde gerçek bir eşzamansız işlevi çağırmak için await kullanırsanız, TÜM işlevleriniz eşzamansız olarak işaretlenmeli ve işlev çağrılarınızın TÜMÜ await kullanmalıdır.

Bu, esas olarak, tüm uygulamanızdaki tüm işlevlere, çoğu zaman uyumsuz olmayan ve hiçbir zaman eşzamansız olmayacak olan sözlerin ek yükünü eklemeniz gerektiği anlamına gelir.

Gerçekten düşünürseniz, bir işlevde await kullanmak, await anahtar sözcüğünü içeren işlevin ASYNC OLMAMASINI gerektirmelidir - bunun nedeni, await anahtar sözcüğünün, await anahtar sözcüğünün bulunduğu işlevde işlemeyi duraklatmasıdır. Bu işlevde işlem duraklatılırsa, kesinlikle eşzamansız DEĞİLDİR.

Bu nedenle, javascript ve ECMAScript geliştiricilerine - lütfen await / async uygulamasını aşağıdaki gibi düzeltin ...

  • await yalnızca CALL async işlevleri için kullanılabilir.
  • await, eşzamanlı veya eşzamansız herhangi bir işlevde görünebilir.
  • "Await yalnızca eşzamansız işlevde geçerlidir" olan hata iletisini, "await yalnızca eşzamansız işlevleri çağırmak için kullanılabilir" olarak değiştirin.

İstersen buna böcek diyebilirsin, ama ben katılmıyorum. "Duraklatan" kod diye bir şey yoktur - daha ziyade, bazı harici işlemlerin (genellikle io) sonuçları olmadan tamamlanamayan kod vardır. Tek iş parçacıklı javascript VM'nin aksine, birçok harici işlemin aynı anda (eşzamanlı olmayan) çalışabilmesi gerektiğinden, bu tür bir kod "eşzamansız" olarak adlandırılmalıdır. Yeniden yapılandırılması gereken birçok işleviniz varsa, bu, işlevlerinizin asyncçoğunun harici işlemlerin sonuçlarını gerektirdiği gerçeğini yansıtır. Bence bu tamamen kanonik.
Gershom

Ayrıca await, yalnızca işlev çağrılarıyla kullanılabilecek şekilde kısıtlanmanın korkunç bir dezavantajından bahsetmeye değer : tek bir harici işlem için, bu işlem tamamlandığında javascript kodundaki yalnızca tek bir nokta bildirilebilir. Örneğin, bir dosyanın içeriğine 3 bağımsız amaç için ihtiyaç duyulursa, her bir amacın bağımsız olarak yapması gerekir let content = await readTheFile();- bunun nedeni, "dosyanın içeriğinin vaadinin" beklenememesidir, yalnızca "dosyayı okuma ve bir kez dosyaya devam etme eylemidir. "okuyun.
Gershom

Tamam, onu duraklatan kod ya da tamamlanamayan kod demeyelim, ama bloke beklemeye ne dersiniz? İşte ov - beklemede engellenen veya tamamlanamayan işlev, await anahtar sözcüğünü içeren işlevdir. Await anahtar sözcüğüyle çağrılan zaman uyumsuz işlev değildir. Bu nedenle, await anahtar sözcüğünü içeren işlevin kesinlikle eşzamansız olarak işaretlenmesi GEREKMEMELİDİR - eşzamansızın tersi olan beklemede bloke edilir.
Rodney P. Barbati

Bunu tamamen açıklığa kavuşturmak için, şunu göz önünde bulundurun - await, eşzamanlı olmayan işlevlerin eşzamanlı görünmelerini sağlayarak (yani işleri belirli bir sırayla yapmama izin vererek) eşzamansız işlevlerin kullanımını basitleştirmeyi amaçlamaktadır. Beklemeyi içeren işlevi eşzamansız olmaya zorlamak, tam bir yanlış isimlendirmedir - eşzamanlı hale gelmesi için beklemeyi kullandınız. Bir await içeren bir işlev, akla gelebilecek her şekilde kesinlikle bir eşzamansız işlev DEĞİLDİR !!!
Rodney P. Barbati

1
@Gershom - kulağa mantıklı geliyor. Teşekkürler!
Rodney P. Barbati
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.