0

How can I save all of the json into my mongoldb? Strangely, only the first value is stored every time. It might be blocking/non-blocking issue.

json = {
  ["name":"Karl","id":"azo0"],
  ["name":"Robert","id":"bdd10"],
  ["name":"Joan","id":"difj90"],
  ["name":"Hallyn","id":"fmak88"],
  ["name":"Michael","id":"vma91"]
};

for(var i = 0; i < json.length; i++){
  id = json[i].id;
  name = json[i].name;

  var ctx = {"id":id,"name":name};
  db.json_db.count(ctx).exec(function(err, count) {
    if(count < 1){
        var model = new User({
           "name":json[i].name,
           "id":json[i].id
        });
        model.save(function(){
            console.log("ok"+i);

        });
    }
  });
};

After inserting, all of datas are filled with ["name":"Karl","id":"azo0"] To check out console.log("ok"+i), it prints always "ok0" not "ok1", "ok2", "ok3"... etc..

How can I prevent this issue?

user207421
  • 305,947
  • 44
  • 307
  • 483
Richard
  • 351
  • 4
  • 17
  • 1
    FWIW: There is only **one** variable called `i` in the code: the same variable is accessed from each distinct closure. That said, I'd expect it to print "ok*5*" if it's truly asynchronous.. – user2864740 May 12 '18 at 01:25
  • 2
    See https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example ; also, ES-6 has `let`, see https://stackoverflow.com/questions/41892488/closures-versus-es6-let – user2864740 May 12 '18 at 01:28
  • 1
    Perfect!!!! Thank you user2864740 :) – Richard May 12 '18 at 10:36

2 Answers2

1

.exec() tells me you're using Mongoose. So your loop can rewritten as:

const json = [
  {name: "Karl", id: "azo0"},
  {name: "Robert", id: "bdd10"},
  {name: "Joan", id: "difj90"},
  {name: "Hallyn", id: "fmak88"},
  {name: "Michael", id: "vma91"}
];

for (const item of json) {
  const count = await db.json_db.count(item).exec()
  if (!count) {
    await new User(item).save()
  }
}
Cisco
  • 20,972
  • 5
  • 38
  • 60
  • Thank you Mateo, Maybe that’s because everyone is basically used "var" instead of "let", "const". Thanks to you I can resolve my case :) – Richard May 12 '18 at 10:34
1

Incase you're using Async package, this is an best way to solve your problem...

  async.eachSeries(json, (item, done) => {
   let user = new User(
                     {
                        "name":json[i].name,
                         "id":json[i].id
                    },
                    (err, user) => {
                        if(err){
                           // handle err
                        }
                        return done();
                    }
                );
});
Truong Dang
  • 3,119
  • 1
  • 15
  • 21