동기 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.allPromise.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.