Typescript: Fehler in async / await beim Ausführen einer "return" -Anweisung innerhalb einer for-Schleife, die in einer asynchronen Funktion wartet

Erstellt am 19. Aug. 2015  ·  3Kommentare  ·  Quelle: microsoft/TypeScript

Im aktuellen Prototyp der Async / Await-Downlevel-Unterstützung haben wir festgestellt, dass ein Fehler dazu führt, dass im Code eine fehlerhafte Ausnahme auftritt, die ansonsten funktionieren sollte.

Repro:

Der Kern des Problems besteht darin, dass eine "return" -Anweisung

Führen Sie diesen Code aus, und Sie werden feststellen, dass immer dann, wenn die Anweisung "num"> .5 ist (und die Anweisung "return true" ausgewertet wird), der folgende Fehler im __generator-Code angezeigt wird: "TypeError: Eigenschaft kann nicht abgerufen werden." '0' der undefinierten oder Nullreferenz ”

    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);
    });

Analyse:

Das Problem wird durch die Anweisung "return" in der Schleife verursacht. Wenn ich itemExists () geändert hätte, um beispielsweise eine lokale Variable festzulegen, und dann über eine "break" -Anweisung aus der Schleife ausbrechen würde, würde der Code funktionieren:

    // 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;
   }

Eine schnelle Analyse des Problems scheint im generierten Code enthalten zu sein. Die Ausnahme ist hier einwerfen:

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

Der eigentliche Schuldige scheint jedoch in der Tatsache zu liegen, dass die generierte Return- und Break-Anweisung eine Inkonsistenz aufweist (soweit ich das beurteilen kann). 3 sieht nämlich aus wie eine "Pause" und manchmal eine "Rückkehr".

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

Hilfreichster Kommentar

@ d180cf wir arbeiten daran :)

Alle 3 Kommentare

Diese Zustandsmaschine sieht aus wie eine Absenkung von Generatoren. Bedeutet das, dass [email protected] yield wenn es auf es5 abzielt?

@ d180cf wir arbeiten daran :)

Ab 4685646, der neuen Version dieser Downlevel-Transformationen für asynchrone Funktionen, die wir für unsere Version 2.1 anstreben, sollte dies kein Problem mehr sein.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen