Im aktuellen Prototyp der Async / Await-Downlevel-Unterstützung haben wir festgestellt, dass ein Fehler dazu führt, dass im Code eine fehlerhafte Ausnahme auftritt, die ansonsten funktionieren sollte.
Der Kern des Problems besteht darin, dass eine "return" -Anweisung
Führen Sie diesen Code aus, und Sie werden feststellen, dass immer dann, wenn die Anweisung "num"> .5 ist (und die Anweisung "return true" ausgewertet wird), der folgende Fehler im __generator-Code angezeigt wird: "TypeError: Eigenschaft kann nicht abgerufen werden." '0' der undefinierten oder Nullreferenz ”
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);
});
Das Problem wird durch die Anweisung "return" in der Schleife verursacht. Wenn ich itemExists () geändert hätte, um beispielsweise eine lokale Variable festzulegen, und dann über eine "break" -Anweisung aus der Schleife ausbrechen würde, würde der Code funktionieren:
// 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;
}
Eine schnelle Analyse des Problems scheint im generierten Code enthalten zu sein. Die Ausnahme ist hier einwerfen:
try {
var operation = body(state);
opcode = operation[0], arg = operation[1];
} catch (e) {
opcode = 1 /*throw*/, arg = e;
}
Der eigentliche Schuldige scheint jedoch in der Tatsache zu liegen, dass die generierte Return- und Break-Anweisung eine Inkonsistenz aufweist (soweit ich das beurteilen kann). 3 sieht nämlich aus wie eine "Pause" und manchmal eine "Rückkehr".
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);
});
Diese Zustandsmaschine sieht aus wie eine Absenkung von Generatoren. Bedeutet das, dass [email protected] yield
wenn es auf es5 abzielt?
@ d180cf wir arbeiten daran :)
Ab 4685646, der neuen Version dieser Downlevel-Transformationen für asynchrone Funktionen, die wir für unsere Version 2.1 anstreben, sollte dies kein Problem mehr sein.
Hilfreichster Kommentar
@ d180cf wir arbeiten daran :)