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.
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);
});
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);
});
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.
Comentario más útil
@ d180cf estamos trabajando en ello :)