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.
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);
});
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);
});
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.
Comentários muito úteis
@ d180cf estamos trabalhando nisso :)