Исправить для реализации цикла
Я написал некоторый код для преобразования документации 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 ответа
Вы стали жертвой ограниченных правил 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
даже если он используется внутри асинхронного обратного вызова.
Вы выполняете цикл правильно, однако проблема в том, что JavaScript не создает замыкание для for
тело. Поскольку вы запускаете асинхронную операцию в цикле, значение i
изменилось к тому времени, когда асинхронная операция завершилась и ваш обратный вызов был вызван.
Таким образом, вам нужно будет создать замыкание непосредственно в цикле for, сохранить требуемое значение внутри замыкания, а затем вызвать асинхронную операцию, одновременно определяя обратный вызов внутри замыкания.
for(var i = 0; i < resourcesArray.length; i++) {
(function(i) {
// Do work here with the value i
})(i);
}
Это может произойти, потому что внутри вашего асинхронного вызова for
петля. Вам нужно заморозить значение i
для каждой итерации. Ты можешь использовать closure()
за это. Если вы хотите отслеживать, когда все итерации завершены, вы можете сохранить счетчик:
var counter = resourcesArray.length;
for(var i = 0; 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