Typescript: Bug dans async / await lors de l'exécution d'une instruction "return" à l'intérieur d'une boucle for qui attend dans une fonction async

Créé le 19 août 2015  ·  3Commentaires  ·  Source: microsoft/TypeScript

Dans le prototype actuel du support de niveau inférieur Async / Await, nous avons trouvé qu'un bogue provoque une exception erronée dans le code qui devrait autrement fonctionner.

Repro:

L'essentiel du problème est que le fait d' avoir une instruction «return» à l'intérieur d'une boucle for dans une fonction qui contient une attente provoque une erreur .

Exécutez ce code et vous verrez que chaque fois que le "num" est> .5 (et que l'instruction "return true" est évaluée), vous obtenez l'erreur suivante qui provient du code __generator: "TypeError: Unable to get property "0" de référence non définie ou nulle "

    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:

Le problème est causé par l'instruction «return» dans la boucle. Si j'avais modifié itemExists () pour définir une variable locale, par exemple, puis sortir de la boucle via une instruction «break», le code fonctionnerait:

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

Une analyse rapide du problème semble se trouver dans le code généré. L'exception est jetée ici:

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

Mais le véritable coupable semble être dans le fait qu'il y a une incohérence dans l'instruction return and break générée (pour autant que je sache). À savoir, 3 ressemble parfois à une «pause» et parfois à un «retour».

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

Commentaire le plus utile

@ d180cf nous y travaillons :)

Tous les 3 commentaires

Cette machine d'état ressemble à un émetteur de bas niveau de générateurs. Cela signifie-t-il que [email protected] va prendre en charge yield lors du ciblage d'es5?

@ d180cf nous y travaillons :)

Cela ne devrait plus être un problème à partir de 4685646, qui est la nouvelle version de ces transformations de bas niveau pour les fonctions asynchrones que nous ciblons pour notre version 2.1.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

kyasbal-1994 picture kyasbal-1994  ·  3Commentaires

weswigham picture weswigham  ·  3Commentaires

bgrieder picture bgrieder  ·  3Commentaires

MartynasZilinskas picture MartynasZilinskas  ·  3Commentaires

DanielRosenwasser picture DanielRosenwasser  ·  3Commentaires