更正 for 循环实现
Correct for loop implementation
我已经编写了一些代码来将 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());
})
}
这可能是因为在您的 for
循环中有一个异步调用。您需要为每次迭代冻结 i
的值。您可以为此使用 closure()
。如果您想跟踪所有迭代何时完成,您可以保留一个计数器:
var 计数器 = resourcesArray.length;
for(var i = 0; i < resourcesArray.length; i++) {
var resources = resourcesArray[i];
(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
您循环正确,但问题是 JavaScript 没有为 for
主体创建闭包。由于您在循环中启动异步操作,因此 i
的值在异步操作完成并调用您的回调时已更改。
所以你必须立即在 for 循环中创建一个闭包,在闭包中存储你想要的值,然后在闭包中定义回调的同时调用异步操作。
for(var i = 0; i < resourcesArray.length; i++) {
(function(i) {
// Do work here with the value i
})(i);
}
您已成为 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 循环块将始终包含 i
的预期值,即使它在异步回调中使用也是如此。
我已经编写了一些代码来将 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());
})
}
这可能是因为在您的 for
循环中有一个异步调用。您需要为每次迭代冻结 i
的值。您可以为此使用 closure()
。如果您想跟踪所有迭代何时完成,您可以保留一个计数器:
var 计数器 = resourcesArray.length;
for(var i = 0; i < resourcesArray.length; i++) {
var resources = resourcesArray[i];
(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
您循环正确,但问题是 JavaScript 没有为 for
主体创建闭包。由于您在循环中启动异步操作,因此 i
的值在异步操作完成并调用您的回调时已更改。
所以你必须立即在 for 循环中创建一个闭包,在闭包中存储你想要的值,然后在闭包中定义回调的同时调用异步操作。
for(var i = 0; i < resourcesArray.length; i++) {
(function(i) {
// Do work here with the value i
})(i);
}
您已成为 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 循环块将始终包含 i
的预期值,即使它在异步回调中使用也是如此。