Typescript: Error en async / await al hacer una declaración "return" dentro de un bucle for que espera en una función async

Creado en 19 ago. 2015  ·  3Comentarios  ·  Fuente: microsoft/TypeScript

En el prototipo actual del soporte de nivel inferior Async / Await, encontramos que un error provoca que ocurra una excepción errónea en el código que de otra manera debería funcionar.

Repro:

La esencia del problema es que tener una declaración "return" dentro de un bucle for en una función que tiene un await provoca un error .

Ejecute este código y verá que siempre que "num" es> .5 (y se evalúa la declaración "return true"), obtiene el siguiente error que proviene del código __generator: "TypeError: No se puede obtener la propiedad '0' de referencia nula o indefinida "

    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álisis:

El problema es causado por la declaración "return" dentro del ciclo. Si hubiera modificado itemExists () para establecer una variable local, por ejemplo, y luego salir del bucle a través de una declaración "break", el código funcionaría:

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

Un análisis rápido del problema parece estar en el código generado. La excepción se incluye aquí:

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

Pero el verdadero culpable parece estar en el hecho de que hay una inconsistencia en la declaración de retorno y ruptura generada (hasta donde yo sé). Es decir, 3 parece en algún momento un "descanso" y, a veces, un "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

Comentario más útil

@ d180cf estamos trabajando en ello :)

Todos 3 comentarios

Esta máquina de estado parece una emisión de generadores de nivel inferior. ¿Significa que [email protected] admitirá yield al apuntar a es5?

@ d180cf estamos trabajando en ello :)

Esto ya no debería ser un problema a partir de 4685646, que es la nueva versión de estas transformaciones de nivel inferior para funciones asíncronas a las que nos dirigimos para nuestra versión 2.1.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

jbondc picture jbondc  ·  3Comentarios

uber5001 picture uber5001  ·  3Comentarios

MartynasZilinskas picture MartynasZilinskas  ·  3Comentarios

Roam-Cooper picture Roam-Cooper  ·  3Comentarios

kyasbal-1994 picture kyasbal-1994  ·  3Comentarios