Typescript: Bug em async / await ao fazer uma instrução "return" dentro de um loop for que aguarda em uma função assíncrona

Criado em 19 ago. 2015  ·  3Comentários  ·  Fonte: microsoft/TypeScript

No protótipo atual do suporte de nível inferior Async / Await, descobrimos que um bug faz com que uma exceção errônea ocorra no código que, de outra forma, deveria funcionar.

Repro:

A essência do problema é que ter uma instrução “return” dentro de um loop for em uma função que possui um await causa um erro .

Execute este código e você verá que sempre que “num” for> .5 (e a instrução “return true” for avaliada), você obterá o seguinte erro que vem de dentro do código __generator: “TypeError: Unable to get property '0' de referência indefinida ou nula ”

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

Análise:

O problema é causado pela instrução “return” dentro do loop. Se eu tivesse modificado itemExists () para definir uma variável local, por exemplo, e depois sair do loop por meio de uma instrução “break”, o código funcionaria:

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

Uma análise rápida do problema parece estar no código gerado. A exceção é lançada aqui:

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

Mas o verdadeiro culpado parece estar no fato de que há uma inconsistência no retorno gerado e na instrução break (até onde posso dizer). Ou seja, 3 parece às vezes uma “pausa” e às vezes um “retorno”.

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

Comentários muito úteis

@ d180cf estamos trabalhando nisso :)

Todos 3 comentários

Esta máquina de estado parece uma emissão de geradores de nível inferior. Isso significa que [email protected] suportará yield ao direcionar es5?

@ d180cf estamos trabalhando nisso :)

Isso não deve ser mais um problema a partir de 4685646, que é a nova versão dessas transformações de nível inferior para funções assíncronas que pretendemos para nosso lançamento 2.1.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

weswigham picture weswigham  ·  3Comentários

CyrusNajmabadi picture CyrusNajmabadi  ·  3Comentários

uber5001 picture uber5001  ·  3Comentários

jbondc picture jbondc  ·  3Comentários

manekinekko picture manekinekko  ·  3Comentários