【问题标题】:FindOne inside save inside a for loopFindOne 在 for 循环中保存
【发布时间】:2017-07-29 15:07:23
【问题描述】:

大家好,我正在尝试使用这段代码,我很确定这里存在一个涉及 MongoDB findOne 并保存在 for 循环中的异步问题。

   restArray.forEach(function(restArr)
    {
         var temp = new Restaurant ({
               nameOfRest: restArr.restaurant.name,
               favoriteFoods:[],
    });
                    console.log(restArr.restaurant.name);
            //Find a restaurant and if it can't find one:
           //Set up a new one. 
          Restaurant.findOne({nameOfRest: restArr.restaurant.name}).then(function(err,data){
                    if(err){
                        console.log("Error in finding.");
                    }

                    else if(!data)
                    {
                        //console.log(temp);
                        temp.save().then(function(err){
                            if(err) {
                                console.log("Error in saving");
                            }
                        });
                    }
                     //console.log(data);
                });
     });

我一直在尝试查看文档,但仍然无法弄清楚。

【问题讨论】:

  • 你是对的。如果你想运行这些东西,要么使用 forEach 循环,要么使用 node.js 的 async 模块会更好
  • 单独一个 forEach 循环会解决我的问题,还是我需要一个 forEach 循环和异步模块?
  • forEach 将解决您的问题,但我们不应该这样做,因为它同步运行并且可能导致回调地狱..所以我更喜欢使用 async 模块,这将使我的代码很多更干净更轻松
  • 你能举个例子说明我在我的情况下会做什么吗?
  • 您遇到了竞争条件问题。 Restaurant.findOne 将在找到第一个文档时做出响应,然后引用 temp,这将是最后创建的项目。如果您希望它在您的代码上下文中工作,那么创建一个专用于查找文档的新函数。请在下面*****已更新****下查看我的答案的底部

标签: node.js mongodb asynchronous


【解决方案1】:

我在大约 8 个月前投入到节点中,并有反复试验的伤痕来证明这一点。
希望我可以通过向您介绍 Promise 来为您省去一些麻烦。这将使代码具有高性能、可读性、避免竞争条件和有希望

这是您的语法的重新格式化版本。

const Mongoose = require('mongoose');
const Promise = require('bluebird'); // Promise library

Mongoose.Promise = Promise; // Set mongoose to use bluebird as the promise library.  Bluebird comes with a lot of useful promise utilities not found in the stock Promise library. 

let restaurants = ["kfc", "churcheschicken", "chicken and waffles"];

let promises = [];

restaurants.forEach((name, idx, arr) => {

    promises.push(Mongoose.models.Restaurant.findOne({ "nameOfRest": name })); 

})


// handle all errors
let onAllErrors = function(err){
    // do something with errors
}

let onDocumentSaved = function(newSavedDocument){ 
    // do something with saved document
}


// Run array of promises through this chain.
Promise.mapSeries(promises, (rest, idx, length) => {

        //rest will be a model found in your database

        if (!rest) { //not found, lets create a new restaurant
            let newRest = new Mongoose.models.Restaurant({
                nameOfRest: restaurants[idx],
                favoriteFoods:[],
            })
            // return items will be found in RESULTS in the next .then chain
            return newRest.save().then(onDocumentSaved).catch(onAllErrors);
        }
    })
    .then(RESULTS => {
        // returned from above
    })
    .catch(onPromiseError));

******* 更新 *******

var findOrCreate = function(){
    console.log(restArr.restaurant.name);
    //Find a restaurant and if it can't find one:
    //Set up a new one. 
    Restaurant.findOne({nameOfRest: this.nameOfRest})
        .then(exist => {
            if (!exist) {
                this.save()
                    .then(result => {
                        console.log(result);
                        //document saved
                    })
                    .catch(err => {
                        console.log(err);
                    });
            }
        })
        .catch(err => {
            debugger;
            //reject(err);
        });
}

restArray.forEach(function(restArr)
    {
         var temp = new Restaurant ({
               nameOfRest: restArr.restaurant.name,
               favoriteFoods:[],

             findOrCreate.call(temp);
    });

});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-25
    • 2021-07-28
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 2019-08-09
    • 2019-10-24
    相关资源
    最近更新 更多