동기 iterable과 함께 await…


11

MDN에 따르면 for await...of 두 가지 사용 사례가 있습니다.

이 for await...of명령문은 비동기 반복 가능 오브젝트와 동기화 반복 가능 오브젝트를 반복하는 루프를 작성합니다.

나는 이전을 알고 있었다 : async iterables using Symbol.asyncIterator. 그러나 나는 이제 후자에 관심이있다 : 동기 iterables.

다음 코드는 동기식 iterable-약속 배열을 반복합니다. 각 약속의 성취에 대한 절차를 막는 것으로 보입니다.

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
질문이 정확히 무엇입니까? 그것은 당신이 작업을 제공 한 예처럼 보인다
— Sagi Rika

for await... of동기 이터 러블에 대한 설명은 정확합니까? 그렇다면 패턴이 처리되지 않은 거부 오류를 발생시킬 수 있는가?
— 벤 애스턴

"정확하다"는 질문이 아닙니다. "올바른"은 당신이 말하는 것입니다.
— Robert Harvey

설명 된 처리되지 않은 거부 오류의 발생을 코드를 통해 보여줄 수 있습니까?
— Robert Harvey

마지막 코드가이를 보여줍니다. 내가하고 있다고 생각하는 것을 설명하는 코드를 제공했기 때문에이 맥락에서 올바른 의미를 갖습니다. 동작이 내 코드와 일치하면 내 코드가 정확하고 그렇지 않으면 내 이해가 올바르지 않습니다. 또한 "정확한" 관찰 은 당신이 말하는 것입니다. 분명히 사실이 아닙니다. 이 문맥에서 올바른 것은 잘 정의 된 의미를 갖습니다.
— 벤 애스턴

답변:


4

예, 이상합니다. 이렇게하면 안됩니다. 약속의 배열을 반복하지 마십시오 . 언급 한 처리되지 않은 거부 문제가 발생합니다 .

왜 이것이 언어로 지원됩니까? 조잡한 약속 의미론을 계속합니다.

제안서 의이 부분을 논의하는 문제에 대한이 의견 에서 정확한 추론을 찾을 수 있습니다 .

Symbol.iterator현재 Promise 시맨틱은 동기화 사물을 비동기식으로 사용하도록 허용하는 것에 관한 것이므로 다시 돌아 가야한다고 생각합니다 . 이것을 "느슨 함"이라고 부를 수 있습니다. 위의 @groundwater의 논리를 따르지 만, 더 자세히 병렬을 철자하고 싶습니다.

"체인"시맨틱 .then은 이것에 관한 것입니다. 약속 .then또는 스칼라 값을 반환 할 수 있습니다 . 모두 동일합니다. 당신은 전화 Promise.resolve약속에 뭔가를 포장하지,하지만 약속에 캐스팅 뭔가 - 당신이 뭔가 - 또는 - 다른이있을 때 비동기 값을 가져옵니다.

의 의미 async와는 await물론 정치 못한 것에 대해 모두. await비동기 함수에서 Promise가 아닌 표현식을 때릴 수 있으며 작업 대기열에 대한 제어 권한을 얻는 것을 제외하고는 모든 방식이 정확하게 동일하게 작동합니다. 마찬가지로, 결과가있는 한 async 원하는대로 "방어 적으로"넣을 수 await있습니다. 약속을 반환하는 함수가 있다면 무엇이든! 그 async기능을 만들 수 있고, 사용자 관점에서는 아무런 변화가 없습니다 (기술적으로 다른 Promise 객체를 가져와도).

비동기 반복자와 생성기는 같은 방식으로 작동해야합니다. 실수로 약속이 아닌 값을 기다리는 것처럼 합리적인 사용자는 yield*비동기 생성기 내에서 동기화 반복기 를 사용할 수있을 것으로 기대합니다 . for await사용자가 방어적인 방식으로 루프를 표시하는 경우 루프가 비동기 반복자를 얻을 수 있다고 생각하면 루프도 마찬가지로 "작동"해야합니다.

이러한 모든 유사점을 깨뜨리는 것이 큰 일이라고 생각합니다. 비동기 반복자를 덜 인체 공학적으로 만듭니다. 다음에 비동기 생성기 / 반복기가 TC39의 안건에 등장 할 때 이에 대해 논의 해 봅시다.


감사합니다. 이벤트가 발생합니까 아니면 실제로 다른 종류의 오류입니까? 이벤트가 WebAPI의 일부라고 생각했기 때문에 묻습니다. 이벤트 방출이 스펙의 다른 부분에서도 비슷한 방식으로 사용됩니까?
— 벤 애스턴

@ 52d6c6af unhandledrejection이벤트 를 언급하고 있습니까?
— Bergi

예. 내가 사용한 "오류"를 가로채는 것만으로 window.addEventListener('unhandledrejection',...간단히 말해서, 이것은 JavaScript에 의한 이런 종류의 오류 방출을 염두에 둘 수있는 유일한 사례입니다. 그러나 나는 이것을 생각하는 것이 거의 잘못되었습니다. 마지막으로,이 "오류"의 방출이 콘솔에 원치 않는 오류 메시지를 갖는 것 이상으로 중요한가?
— 벤 애스턴

1
@ 참조 52d6c6af 여기 와 거기에 이이 ECMAScript를 웹 API 사양의 공동 노력에 지정된 방법에 대한. 아니요, 이벤트는 중요하지 않습니다. 이벤트를 받았을 때 이미 너무 늦었습니다. Afaics는 클라이언트 측 오류 모니터링에만 사용됩니다.
— 베르 기

실제로 중요하지 않은 경우, 조언이 여전히 "약속의 약속을 반복하지 마십시오"입니까, 아니면 "일부 상황에서는 이것이 빠른 동작을 나타내지 않는다"는 것입니까?
— 벤 애스턴

0

sad약속은 하지 않습니다 되는 await코드의 요구에 대기 완료하는 것을 - 그것이 실패했을 때 ED happy가에 기다릴 시작하기 전에 sad. sad약속은 전에 실패 happy해결합니다. ( Promise.all이 사용 사례에 더 적합한 도구입니다)


1
알아. 따라서 내 질문. Promise.all더 나은 솔루션 이라면 왜이 언어가이 구문을 제공합니까? for await...of비동기 이터 러블을 간단히 열거하기 위해 쉽게 구현할 수있었습니다. 그러나 그들은 동기 iterable을 열거하기 위해 (그러나 (?) 함정으로) 수용했습니다. 왜?
— 벤 애스턴

1
아, 나는 오해했다. for await ... of동기 이터 러블을 허용하는 이유를 묻고 있습니까? 조건부로 동기 항목을 반환 할 수있는 비동기 생성기를 지원한다고 상상합니다.
— Gershom

그렇습니다. 특히 거부 배선 함정을 도입하는 것처럼 보입니다.
— 벤 애스턴

내 생각에 함정은 더 일반적으로 약속을 만들고 즉시 기다리지 않는 약속에 있습니다. 불행히도이 함정은 종종 매우 유용한 기능입니다.
— Gershom
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.