Typescript: 비동기 ν•¨μˆ˜μ—μ„œ λŒ€κΈ°ν•˜λŠ” for 루프 λ‚΄μ—μ„œ "return"문을 μˆ˜ν–‰ ν•  λ•Œ async / await의 버그

에 λ§Œλ“  2015λ…„ 08μ›” 19일  Β·  3μ½”λ©˜νŠΈ  Β·  좜처: microsoft/TypeScript

Async / Await ν•˜μœ„ μ§€μ›μ˜ ν˜„μž¬ ν”„λ‘œν†  νƒ€μž…μ—μ„œ λ²„κ·Έλ‘œ 인해 μ½”λ“œμ—μ„œ 잘λͺ»λœ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λŠ” 것을 λ°œκ²¬ν–ˆμŠ΅λ‹ˆλ‹€.

μž¬ν˜„ :

문제의 μš”μ§€ λŠ” awaitκ°€μžˆλŠ” ν•¨μˆ˜μ˜ for 루프 내뢀에 "return"문이 있으면 였λ₯˜κ°€ λ°œμƒν•œλ‹€λŠ” 것 μž…λ‹ˆλ‹€.

이 μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ "num"이> .5 (그리고 "return true"문이 평가 될 λ•Œλ§ˆλ‹€) __generator μ½”λ“œ λ‚΄μ—μ„œ λ‹€μŒκ³Ό 같은 였λ₯˜κ°€ λ°œμƒν•˜λŠ” 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. "TypeError : Unable to get property '0'of undefined or null reference”

    async function itemExists(): Q.Promise<boolean> {
        var numTries = 3;
        for (var i = 0; i < numTries; i++) {
            var num = await Q.fcall(function() { return Math.random() });
            console.log(num);
            if (num > .5) {
                return true;
            }
        }
        return false;
    }

    itemExists().then(function(val) {
        console.log("All values greater than .5: " + val)
    }).catch(function(e) {
        console.error("Error: " + e);
    });

뢄석:

λ¬Έμ œλŠ” 루프 λ‚΄μ˜β€œreturnβ€λ¬ΈμœΌλ‘œ 인해 λ°œμƒν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, 지역 λ³€μˆ˜λ₯Ό μ„€μ •ν•˜κΈ° μœ„ν•΄ itemExists ()λ₯Ό μˆ˜μ • ν•œ λ‹€μŒ "break"문을 톡해 루프λ₯Ό λ²—μ–΄λ‚˜λ©΄ μ½”λ“œκ°€ μž‘λ™ν•©λ‹ˆλ‹€.

    // With workaround (NOT short-circuiting the loop)
    async function itemExists(): Q.Promise<boolean> {
        var numTries = 3;
        var result = false;
        for (var i = 0; i < numTries; i++) {
            var num = await Q.fcall(function() { return Math.random() });
            console.log(num);
            if (num > .5) {
                result = true;
                break;
            }
        }
        return result;
   }

λ¬Έμ œμ— λŒ€ν•œ λΉ λ₯Έ 뢄석은 생성 된 μ½”λ“œμ—μžˆλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. μ˜ˆμ™ΈλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

            try {
                var operation = body(state);
                opcode = operation[0], arg = operation[1];
            } catch (e) {
                opcode = 1 /*throw*/, arg = e;
            }

κ·ΈλŸ¬λ‚˜ μ‹€μ œ 범인은 생성 된 return 및 break 문에 λΆˆμΌμΉ˜κ°€ μžˆλ‹€λŠ” 사싀 인 것 κ°™μŠ΅λ‹ˆλ‹€ (λ‚΄κ°€ 말할 μˆ˜μžˆλŠ” ν•œ). 즉, 3은 λ•Œλ•Œλ‘œ "νœ΄μ‹"κ³Ό "λ°˜ν™˜"처럼 λ³΄μž…λ‹ˆλ‹€.

function itemExists() {
    return new Q.Promise(function (_resolve) {
        _resolve(__awaiter(__generator(function (_state) {
            switch (_state.label) {
                case 0:
                    numTries = 3;
                    i = 0;
                    _state.label = 1;
                case 1:
                    if (!(i < numTries))
                        return [3 /*break*/, 4];
                    return [4 /*yield*/, Q.fcall(function () {
                        return Math.random();
                    })];
                case 2:
                    num = _state.sent;
                    console.log(num);
                    if (num > .5) {
                       return [3 /*return*/, true];
                    }
                    _state.label = 3;
                case 3:
                    i++;
                    return [3 /*break*/, 1];
                case 4:
                    return [2 /*return*/, false];
            }
        })));
    });
    var numTries, i, num;
}
itemExists().then(function (val) {
    console.log("All values greater than .5: " + val);
}).catch(function (e) {
    console.error("Error: " + e);
});
Bug Fixed

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

@ d180cf μš°λ¦¬λŠ” 그것에 λ…Έλ ₯ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€ :)

λͺ¨λ“  3 λŒ“κΈ€

이 μƒνƒœ 머신은 μƒμ„±κΈ°μ˜ ν•˜μœ„ μˆ˜μ€€ 방좜처럼 λ³΄μž…λ‹ˆλ‹€. es5 λ₯Ό νƒ€κ²ŸνŒ… ν•  λ•Œ yield λ₯Ό μ§€μ›ν•œλ‹€λŠ” μ˜λ―Έμž…λ‹ˆκΉŒ?

@ d180cf μš°λ¦¬λŠ” 그것에 λ…Έλ ₯ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€ :)

2.1 릴리슀λ₯Ό λŒ€μƒμœΌλ‘œν•˜λŠ” 비동기 ν•¨μˆ˜μ— λŒ€ν•œ μ΄λŸ¬ν•œ ν•˜μœ„ λ³€ν™˜μ˜ μƒˆ 버전 인 4685646λΆ€ν„°λŠ” 더 이상 λ¬Έμ œκ°€λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰