Eşzamanlı yinelemelerde… beklemek için kullanma


11

MDN'nin iki kullanım durumu olduğunu söylüyor for await...of :

for await...ofİterable yanı sıra senkronizasyon Iterables üzerinde nesneleri zaman uyumsuz ifadesi yineleme bir döngü oluşturur ...

Daha öncekinin farkındaydım: kullanarak asenkron yinelenebilir Symbol.asyncIterator. Ama şimdi ikincisi ile ilgileniyorum: senkron yinelemeler.

Aşağıdaki kod senkronize bir yinelenebilir - bir dizi vaat üzerinden yinelenir. Her vaadin yerine getirilmesi konusundaki ilerlemeyi engelliyor gibi görünmektedir.

async function asyncFunction() {
    try {
        const happy = new Promise((resolve)=>setTimeout(()=>resolve('happy'), 1000))
        const sad = new Promise((_,reject)=>setTimeout(()=>reject('sad')))
        const promises = [happy, sad]
        for await(const item of promises) {
            console.log(item)
        }
    } catch (err) {
        console.log(`an error occurred:`, err)
    }
}

asyncFunction() // "happy, an error occurred: sad" (printed in quick succession, after about 5 seconds)

Davranış, aşağıda gösterilen mantığa göre her bir sözü sırayla beklemeye benziyor gibi görünmektedir. Bu iddia doğru mu?

Ben soruyorum çünkü bu kod paterni kapalı bir ret telsizi tuzağına sahip Promise.allve Promise.allSettledkaçınıyor ve bu kalıbın dil tarafından açıkça destekleneceği garip görünüyor.


2
Sorunuz tam olarak nedir?
Çalıştığınız

for await... ofEşzamanlı yinelenebilirlerle açıklamam doğru mu ve eğer öyleyse, bu kalıbın işlenmeyen reddetme hataları verebileceği önemli mi?
Ben Aston

"Doğru mu?" Bir soru değil. "Doğru" ne derseniz deyin.
Robert Harvey

Tanımladığınız işlenmeyen reddetme hatalarının yayıldığını kod yoluyla gösterebilir misiniz?
Robert Harvey

Son kod bunu gösterir. Doğru, bu bağlamda iyi tanımlanmış bir anlamı vardır, çünkü ben ne yaptığını açıklamak için kod sağladı. Davranış kodumla eşleşirse, kodum doğrudur, aksi takdirde anlayışım yanlıştır. Ayrıca "Doğru" gözlemi ne derseniz odur. açıkça yanlıştır. Doğru, bu bağlamda iyi tanımlanmış bir anlama sahiptir.
Ben Aston

Yanıtlar:


4

Evet, garip ve bunu yapmamalısın. Söz dizilerini tekrarlamayın, tam olarak bahsettiğiniz işlenmeyen reddetme sorununa yol açar .

Peki bu neden dilde destekleniyor? Özensiz söz semantiği ile devam etmek.

Teklifin bu kısmını tartışan sorunun bu yorumunda tam mantığı bulabilirsiniz :

Sanırım geri dönmeliyiz, Symbol.iteratorçünkü mevcut Promise semantiğimiz tamamen senkronize şeylerin asenkron şeyler olarak kullanılmasına izin vermekle ilgilidir. Buna "özensizlik" diyebilirsiniz. Bu izler yukarıdaki yeraltı suyu mantığı @ , ama sadece daha ayrıntılı olarak paralellikler duymak istiyorsun.

"Zincirleme" anlambilimi bununla ilgilidir .then. Bir Söz .thenveya skaler değer döndürebilirsiniz ; hepsi aynı. Bir Promise.resolveSöz'e bir şey sarmamayı değil, bir Söz'e bir şey aktarmayı çağırırsınız - ya da başka bir şey olduğunda asenkron bir değer elde edin.

Anlambilimi asyncve anlamsızlığı da awaitönemlidir. Bir zaman awaituyumsuz işlevinde Promise olmayan herhangi bir ifadeye tokat atabilirsiniz ve iş kuyruğuna denetim vermeniz dışında her şey aynı şekilde çalışır. Benzer şekilde, sonuç async olarak istediğiniz her şeyi "savunmasız" olarak koyabilirsiniz await. Bir Promise döndüren bir fonksiyonunuz varsa - her neyse! bunu bir asyncişlev haline getirebilir ve kullanıcı açısından hiçbir şey değişmez (teknik olarak farklı bir Promise nesnesi çıkarsanız bile).

Asenkron yineleyiciler ve jeneratörler aynı şekilde çalışmalıdır. Tıpkı yanlışlıkla bir Promise olmayan bir değeri beklediğiniz gibi, makul bir kullanıcı yield*bir zaman uyumsuz üreteç içinde bir yineleyiciyi senkronize etmeyi bekleyebilir . for awaitdöngüler benzer şekilde "sadece" bir kullanıcı bu şekilde defansif bir yineleyici alıyor olabileceğini düşünerek bir döngüyü bu şekilde işaretlerse çalışmalıdır.

Bence bu paralelliklerin hepsini kırmak çok önemli olurdu. Asenkron yineleyicileri daha az ergonomik hale getirir. TC39'da asenkron jeneratörler / yineleyiciler bir sonraki gündeme geldiğinde bunu tartışalım.


Teşekkür ederim. Bir olay mı yayılıyor yoksa gerçekte başka bir hata mı? Soruyorum çünkü olayların WebAPI'nin bir parçası olduğunu düşündüm. Olayların emisyonu, spesifikasyonun diğer kısımlarında benzer bir şekilde mi kullanılıyor?
Ben Aston

@ 52d6c6af Olaylardan bahsediyor musunuz unhandledrejection?
Bergi

Evet. window.addEventListener('unhandledrejection',...Kısacası kullandığım "hatayı" durdurmak için : JavaScript tarafından bu tür bir hata emisyonunun akla getirebileceğim tek örneğidir. Ancak bunu düşünmek neredeyse kesinlikle yanılıyorum. Son olarak: bu "hatanın" emisyonu, konsolda istenmeyen bir hata mesajının olmasının ötesinde gerçekten önemli midir?
Ben Aston

1
@ 52d6c6af ECMAScript ve Web API spesifikasyonları arasındaki ortak bir çabada bunun nasıl belirtildiği için buraya ve oraya bakın . Hayır, olay gerçekten önemli değil, bunu aldığınızda çok geç. Afaics, yalnızca istemci tarafı hatalarını izlemek için kullanılır.
Bergi

Eğer gerçekten önemli değilse, tavsiye hala "vaat dizilerini tekrarlamıyor" mu yoksa daha ziyade "bunun bazı koşullar altında başarısız davranış sergilemediğinin farkında mıdır?"
Ben Aston

0

sadSöz edilmez olma awaitkod ihtiyaçları bekleyen bitirmek olduğunu - bu başarısız olduğunda ed happyo beklemek başlamadan önce sad. Karar sadvermeden önce söz başarısız oluyor happy. ( Promise.allbu kullanım senaryosuna daha uygun bir araçtır)


1
Biliyorum. Dolayısıyla sorum. Eğer Promise.alldaha iyi bir çözüm ise, dil neden bu sözdizimini sağlıyor? for await...ofzaman uyumsuz yinelemeleri basitçe numaralandırmak için kolayca uygulanabilirdi. Ama onlar eşzamanlı yinelemeleri (ama (görünüşte?) Bir tuzak ile saymak için yiyecek ve içecek). Neden?
Ben Aston

1
Ah, yanlış anladım. Neden for await ... ofeşzamanlı yinelemeleri kabul ettiğini mi soruyoruz? Şartlı olarak eşzamanlı öğeler döndürebilen asenkron jeneratörleri desteklemeyi hayal ediyorum.
Gershom

Evet, özellikle bir ret telsiz tuzağı getirdiği göz önüne alındığında.
Ben Aston

Benim düşünceme göre, tuzak daha genel olarak bir vaat yaratmak ve hemen beklememek. Ne yazık ki bu tuzak genellikle çok yararlı bir özelliktir.
Gershom
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.