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.
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);
});
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);
});
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.
Commentaire le plus utile
@ d180cf nous y travaillons :)