2016-07-19 3 views
-2

Я написал код для преобразования документации 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()); 
    }) 
} 
+0

это ... что для циклов делать ... он выполняет итерацию по всему массиву, выполняя то, что внутри. обратный вызов (ы) происходит через некоторое время и не гарантируется в правильном порядке. –

ответ

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 -declared переменных используют лексическую область видимости, это означает, что для блока контура всегда будет содержать ожидаемое значение i даже если он используется внутри асинхронного обратного вызова.

+0

Это очищает меня. Благодаря! – user3221287

-2

Это может происходить потому, что есть асинхронный вызов внутри for цикла. Вам необходимо заморозить значение i, для каждой итерации. Вы можете использовать closure(). Если вы хотите отслеживать, когда все итерации завершены, вы можете сохранить счетчик: var counter = resourcesArray.length; для (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 
1

Вы правильно зацикливание, однако проблема в том, что JavaScript не создает для закрытия for тела. Поскольку вы начинаете асинхронную операцию в цикле, значение i изменилось к моменту завершения асинхронной операции и вызван ваш обратный вызов.

Таким образом, вам нужно будет создать замыкание непосредственно в цикле for, сохранить значение, которое вы хотите в закрытии, а затем вызвать асинхронную операцию, одновременно определяя обратный вызов и в закрытии.

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

Просто обратите внимание, если ES6 является приемлемым, 'for (let i = 0; i

Смежные вопросы