纠正循环实现

时间:2016-07-19 15:21:16

标签: javascript node.js callback order-of-execution

我已经编写了一些代码来将swagger 1文档转换为swagger 2。 我将转换方法指向数组中的多个资源。 我发现它没有正确执行并看到它一直跳到调试器到我的数组的末尾(大小为34)。如何确保它正确循环我的代码?

for(var i = 0; i < resourcesArray.length; i++) {
    Converter.convert({
        from: 'swagger_1',
        to: 'swagger_2',
        source: 'http://example/' + resourcesArray[i]
    }, function (err, converted) {
        console.log(resourcesArray[i]);
        // [Optional] Fill missing fields with dummy values
        converted.fillMissing();

        // [Optional] Validate converted spec
        var fileName = resourcesArray[i] + '.json';
        fs.writeFileSync(fileName, converted.stringify());
    })
}

3 个答案:

答案 0 :(得分:1)

您正在循环,但问题是JavaScript不会为for正文创建闭包。由于您正在循环中启动异步操作,因此i的值在异步操作完成并且已调用回调时已更改。

所以你必须在for循环中立即创建一个闭包,在闭包中存储你想要的值,然后在闭包内定义回调时调用异步操作。

for(var i = 0; i < resourcesArray.length; i++) {
  (function(i) {
    // Do work here with the value i
  })(i);
}

答案 1 :(得分:1)

您已成为JavaScript范围规则的受害者。试试这个:

resourcesArray.forEach(function (resource) {
    Converter.convert({
        from: 'swagger_1',
        to: 'swagger_2',
        source: 'http://example/' + resource
    }, function (err, converted) {
        console.log(resource);
        // [Optional] Fill missing fields with dummy values
        converted.fillMissing();

        // [Optional] Validate converted spec
        var fileName = resource + '.json';
        fs.writeFileSync(fileName, converted.stringify());
    });
});

问题在于,当异步回调function (err, converted) { ... }发生时,i等于resourcesArray.length,因为迭代已经完成。这就是JavaScript var声明变量的工作原理。使用forEach循环可确保范围始终包含您对该操作所期望的resource

或者,如果ES6没问题,那么您可以将var更改为let,这也可以解决问题,因为let - 声明的变量使用词法作用域,这意味着for loop块将始终包含i的预期值,即使它在异步回调中使用。

答案 2 :(得分:-2)

这可能会发生,因为i循环中存在异步调用。对于每次迭代,您需要冻结closure()的值。您可以使用 (function( resources, i ){ Converter.convert({ from: 'swagger_1', to: 'swagger_2', source: 'http://example/' + resources }, function (err, converted) { console.log(resources); // [Optional] Fill missing fields with dummy values converted.fillMissing(); // [Optional] Validate converted spec var fileName = resources + '.json'; fs.writeFileSync(fileName, converted.stringify()); counter--; if( counter <= 0 ) { //next(); } }) })(resources, i ); }//for 。如果您想要跟踪所有迭代何时完成,您可以保留一个计数器:     var counter = resourcesArray.length;     for(var i = 0; i&lt; resourcesArray.length; i ++){       var resources = resourcesArray [i];

{{1}}