Typescript: 在异步函数中等待的for循环内执行“返回”语句时,异步/等待中的错误

创建于 2015-08-19  ·  3评论  ·  资料来源: microsoft/TypeScript

在当前的Async / Await下层支持原型中,我们发现了一个错误导致错误的异常发生在应该以其他方式工作的代码中。

复制:

问题的要点是,在其中具有等待功能的函数的for循环内包含“ return”语句会导致错误

运行此代码,您将发现,每当“ num”大于.5(并且对“ return true”语句进行求值)时,就会从__generator代码中得到以下错误:“ TypeError:无法获取属性未定义或空引用为“ 0””

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

分析:

问题是由循环内的“ return”语句引起的。 例如,如果我修改了itemExists()来设置局部变量,然后通过“ break”语句退出循环,则该代码将起作用:

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

对问题的快速分析似乎在生成的代码中。 在这里抛出异常:

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

但是实际的罪魁祸首似乎是这样一个事实,即所生成的return和break语句不一致(据我所知)。 即,3有时看起来像是“中断”,有时看起来像是“返回”。

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

最有用的评论

@ d180cf我们正在努力:)

所有3条评论

这个状态机看起来像是生成器的下层发射。 定位es5时,是否意味着[email protected]将支持yield

@ d180cf我们正在努力:)

从4685646开始,这应该不再是一个问题,它是我们针对2.1版本针对的异步功能进行的这些下层转换的新版本。

此页面是否有帮助?
0 / 5 - 0 等级