Використання для очікування… із синхронними ітерабелями


11

MDN каже, for await...of що два випадки використання:

for await...ofОператор створює петлю ітерації асинхронної ітерації об'єктів, а також на ітеріруемих синхронізації, ...

Раніше я знав про колишнє: використання асинхронних ітерабелів Symbol.asyncIterator. Але мене зараз цікавить останнє: синхронні ітерабелі.

Наступний код повторюється над синхронним ітерабельним - масивом обіцянок. Схоже, блокують пророків щодо виконання кожної обіцянки.

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)

Поведінка, схоже, сподівається на очікування кожної обіцянки по черзі, згідно логіки, показаної нижче. Чи правильно це твердження?

Я запитую, тому що цей шаблон коду має неявний провал відхилення, який Promise.allі Promise.allSettledуникати, і мені здається дивним, що цей шаблон явно підтримується мовою.


2
Яке саме ваше запитання? Схоже, приклади, які ви надали, працювали
Сагі Ріка

Чи for await... ofправильний мій опис синхронних ітерабелей, і якщо так, чи має значення цей шаблон, який може видавати необроблені помилки відхилення?
Бен Астон

"Це правильно" - це не питання. "Правильно" - це все, що ти кажеш, що воно є.
Роберт Харві

Чи можете ви продемонструвати за допомогою коду видалення описаних вами помилок відхилених помилок?
Роберт Харві

Остаточний код це демонструє. Корект має чітко визначене значення в цьому контексті, тому що я надав код, щоб описати, що я думаю, що це робить. Якщо поведінка відповідає моєму коду, то мій код правильний, інакше моє розуміння неправильне. Також спостереження "Правильно" - це все, що ви говорите. явно не відповідає дійсності. Корекція має чітко визначене значення в цьому контексті.
Бен Астон

Відповіді:


4

Так, це дивно, і ти не повинен цього робити. Не повторюйте масиви обіцянок, це точно призводить до згаданої вами проблеми безвідмовного відхилення .

То чому це підтримується мовою? Продовжуйте неохайну семантику.

Точні міркування ви можете знайти в цьому коментарі питання, що обговорює цю частину пропозиції :

Я думаю, що ми повинні повернутися до цього, Symbol.iteratorоскільки наша поточна семантика Promise - це те, що дозволяє синхронізувати речі як асинхронні речі. Ви можете назвати це "неохайність". Звідси випливає логіка @ підземних вод , але я просто хочу детальніше прописати паралелі.

.thenВсе про це стосується "ланцюгова" семантика . Ви можете повернути Обіцянку від .thenабо скалярного значення; все одно. Ви закликаєте Promise.resolveне обертати щось у Обіцянні, а кинути щось на Обіцянку - отримайте асинхронне значення, коли у вас є щось або інше.

Семантика asyncі awaitвсе стосується того, щоб бути неохайними. Ви можете плескати awaitбудь-який непромітний вираз у функції асинхронізації, і все працює нормально, точно так само, за винятком того, що ви передаєте контроль черзі завдань. Так само ви можете «захисно» обкладати async все, що завгодно, доки ви отримаєте awaitрезультат. Якщо у вас є функція, яка повертає Обіцянку - що завгодно! ви можете зробити цю asyncфункцію, і, з точки зору користувача, нічого не зміниться (навіть якщо технічно ви отримаєте інший об'єкт Promise).

Асинхронізуючі ітератори та генератори повинні працювати однаково. Так само, як ви можете чекати значення, яке, випадково, не було Обіцянням, розумний користувач розраховував би на можливість yield*ітератора синхронізації в генераторі асинхронізації. for awaitциклі повинні аналогічно "просто працювати", якщо користувач захисно позначає цикл таким чином, думаючи, що, можливо, він може отримати асинхронний ітератор.

Я думаю, було б великою справою порушити всі ці паралелі. Це зробить ітератори асинхронізації менш ергономічними. Давайте обговоримо це наступного разу, коли генератори / ітератори асинхронізації з’являться на порядку денному в TC39.


Дякую. Чи випускається подія, чи це насправді якась інша помилка? Я запитую, тому що я вважав, що події були частиною WebAPI. Чи емісія подій використовується аналогічно в інших частинах специфікації?
Бен Астон

@ 52d6c6af Ви посилаєтесь на unhandledrejectionподії?
Бергі

Так. Це просто те, щоб перехопити "помилку", яку я використав window.addEventListener('unhandledrejection',...Коротше: це єдиний екземпляр, який я можу довести до відома, такого виду помилок через JavaScript. Однак я майже напевно помиляюся. Нарешті: чи справді виправдання цієї "помилки" має значення, крім того, що в консолі з'являється повідомлення про небажану помилку?
Бен Астон

1
@ 52d6c6af Тут і там дивіться, як це визначено у спільних зусиллях між специфікаціями ECMAScript та веб-API. Ні, подія насправді не має значення, вже пізно, коли ви це отримали. Afaics, він використовується лише для моніторингу помилок на стороні клієнта.
Бергі

Якщо це насправді не має значення, чи все-таки порада "не повторюйте масиви обіцянок", чи, скоріше, "пам'ятайте, що це не виявляє невдалої поведінки за певних обставин"?
Бен Астон

0

sadОбіцянка НЕ бути під awaitред коли він зазнає невдачі - що потреби коду , щоб закінчити очікування , happyперш ніж він може почати чекати sad. sadОбіцянка не вдається , перш ніж happyвирішує. ( Promise.allчи інструмент краще підходить для цього випадку використання)


1
Я знаю. Звідси моє запитання. Якщо Promise.allкраще рішення, чому мова відповідає цьому синтаксису? for await...ofможна було легко реалізувати для простого перерахування асинхронних ітерабелів. Але вони погоджувались з цим, щоб перерахувати синхронні ітерабелі (але з (здається?) Провалинами). Чому?
Бен Астон

1
Ах, я неправильно зрозумів. Ми запитуємо, чому for await ... ofприймає синхронні ітерабелі? Я б уявив, щоб підтримувати генератори асинхронізації, які умовно можуть повертати синхронні елементи.
Гершом

Так, особливо з огляду на те, що, здається, вводиться провал відхилення.
Бен Астон

На мою думку, гріха є загалом у створенні обіцянки, а не в очікуванні її негайно. На жаль, цей підводний камінь також часто є дуже корисною особливістю.
Гершом
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.