I've written some code to convert swagger 1 documentation to swagger 2. I point the conversion method to several resources in an array. what I find is that it is not executing correctly and see it jump in the debugger all the way to the end of my array (which is of size 34). How do I ensure it loops through my code correctly?
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());
})
}
You've fallen victim to JavaScript scoping rules. Try this:
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());
});
});
The problem was that by the time the asynchronous callback function (err, converted) { ... }
occurs, i
is equal to resourcesArray.length
because the iteration is already complete. That is how JavaScript var
declared variables work. Using a forEach
loop ensures that the scope always contains the resource
you're expecting for that operation.
Alternatively, if ES6 is okay, then you could change var
to let
and that would also solve the problem because let
-declared variables use lexical scoping, which means that the for loop block will always contain the expected value of i
even if it's used inside an asynchronous callback.