0

When using mongojs's function db.collection.createIndex in a for loop, the result is unexpected as shown belo, where the same value of collectionName is passed to createIndex() every single time.

Why is this happening?

Code

var mongojs = require('mongojs');
var db = mongojs(config.get('Mongodb.url'));


for (collectionName of collectionNames) {
    console.log(collectionName);
    db[collectionName].createIndex({'userId': 1}, {'unique': true}, function() {
        console.log('createIndexCB: ', collectionName);
    })
}

Output

Fruits
Juices
Drinks
createIndexCB:  Drinks
createIndexCB:  Drinks
createIndexCB:  Drinks
Nyxynyx
  • 61,411
  • 155
  • 482
  • 830
  • Just create a `let` variable inside the loop. Oddly, it doesn't let you use the same name like `let collectionName=collectionName` because it thinks you're trying to use the new declaration pre-initialization instead of the outer one. Weird. –  Jun 18 '16 at 15:46
  • @squint awesome it works! Can you elaborate on why creating a new variable inside the loop using `let` is needed? Why will a new variable scoped to within the `for` loop help? – Nyxynyx Jun 18 '16 at 15:52
  • `let` is a new, ECMAScript 2015 syntax that lets you create a variable that is scoped to a block instead of a function, like `var` historically has done. However, in the head of your loop, you used neither `let` nor `var`, which means that `collectionName` is a global variable that gets overwritten in each iteration of the loop. So because all the functions are referencing the same global `collectionName` variable, they all see the same value when invoked. Had you done `for (var collectionName of collectionNames) {...`, it wouldn't be global *(unless this was already in the global scope)*... –  Jun 18 '16 at 16:43
  • ...so you'd have the same issue. If it was `for (let collectionName of collectionNames) {...`, you'd *still* have the same issue, because `let` in that position basically puts a block around the entire loop, so it's more like `{let collectionName; for (collectionName of collectionNames) {...} }`. So the only thing left to do is to put the `let` in the block where you make the function, so now each function has its own, unique variable declaration to reference. –  Jun 18 '16 at 16:43
  • ...but hang on a second, this confused me because the `for (let collectionName of collectionNames) {...` is not behaving the same as a `for (let i = 0; i < n; i++) {...` loop, which does scope `i` to the block. I'm testing in Firefox. I then tried in Chrome, and the behavior is consistent. I need to check the spec, but I'm guessing that Firefox is behaving incorrectly. Since you're in NodeJS, try doing `for (let collectionName of collectionNames) {...` and see if that works. That would be a better solution. –  Jun 18 '16 at 16:48
  • @squint Thanks for the explanation! Will test it out soon! – Nyxynyx Jun 18 '16 at 19:35

0 Answers0