2016-09-02 104 views
-1

我是一個nodejs初學者,遇到了一些我不明白的回調行爲。我正在使用Express路由器使用POST請求將Mongoose對象寫入Mongodb。在請求的主體中,我傳遞了嵌套的json結構,其中包含兩個字段 - jobDetailsexamplesjobDetails中的數據用於創建一個Job Mongoose對象,examples中的數據用於創建若干個Example Mongoose對象。 JobExample對象鏈接,因爲Job包含其中一個字段中的Example對象的列表。Node.js與Mongoose發生意外行爲

我試圖實現這一點的方式是用以下方式回調。基本上我首先將Job對象保存爲mongo,然後遍歷示例 - 每次創建一個Example對象並通過.job字段將它鏈接到作業,並將Example對象保存爲mongo。然後在Example對象保存函數的回調中,我使用新的Example對象更新了Job對象,並將更新後的版本保存爲mongo。

router.post('/jobs', function (req, res, next) { 
    var job = new Job(req.body.jobDetails); 
    var examples = req.body.examples; 

    console.log("JOB DETAILS"); 
    console.log(req.body.jobDetails); 

    console.log("EXAMPLES"); 
    console.log(req.body.examples); 

    //save job 
    job.save(function (err, job) { 
      console.log(err); 
    }); 

    //save examples 
    for(i=0; i<examples.length;i++){ 

     var eg = new Example({content: examples[i]}); 
     eg.job=job; 

     eg.save(function (err, eg){ 

      job.examples.push(eg); 

      job.save(function(err, job){ 
       console.log(err); 
      }); 
      console.log(err); 
     }); 
    } 
}); 

這沒有按照我的預期執行。具體來說,實例數量增加了一倍,實際上保存到了mongo中,並且有幾個重複,有些丟失了。我明白,回調是異步的,但對我來說,仍然不能解釋爲什麼將保存兩倍的示例數量,有些會被重複,有些會丟失。

我最終以正確的方式正常工作,沒有按照以下方式使用回調。

router.post('/jobs', function (req, res, next) { 
    var job = new Job(req.body.jobDetails); 
    var examples = req.body.examples; 

    console.log("JOB DETAILS"); 
    console.log(req.body.jobDetails); 

    console.log("EXAMPLES"); 
    console.log(req.body.examples); 

    //save job 
    job.save(function (err, job) { 
      console.log(err); 
    }); 

    //save examples 
    for(i=0; i<examples.length;i++){ 

     var eg = new Example({content: examples[i]}); 
     eg.job=job; 

     eg.save(function (err, eg){ 
      console.log(err); 
     }); 

     job.examples.push(eg); 
     job.save(function(err,job){ 
      console.log(err); 
     }); 
    } 
}); 

而且我不確定這是否是最佳解決方案。但我想知道爲什麼我原來的方法導致了意外的行爲。

回答

0

這應該工作..

router.post('/jobs', function(req, res, next) { 
    var job = new Job(req.body.jobDetails); 
    var examples = req.body.examples; 

    console.log("JOB DETAILS"); 
    console.log(req.body.jobDetails); 

    console.log("EXAMPLES"); 
    console.log(req.body.examples); 

    //save job 
    job.save(function(err, result) { 
     if (!err) { 
      //save examples 
      for (i = 0; i < examples.length; i++) { 

       var eg = new Example({ 
        content: examples[i] 
       }); 
       eg.job = job; 

       eg.save(function(err, eg) { 

        job.examples.push(eg); 

        job.save(function(err, job) { 
         if (!err) 
          job.examples = []; 

        }); 
        console.log(err); 
       }); 
      } 
     } 
    }); 
}); 
+0

你確定了'job.save(函數(ERR,作業){ 如果(ERR) job.examples = [];! });'一部分?這不僅僅是清楚所有的例子嗎? – user1893354

+0

它適合你嗎? 此行在保存後刪除了每個示例,這意味着它不會添加重複項。 – abdulbarik

+0

但所有的例子都必須保存在job.examples中。如果在每個job.save之後清除示例,是不是會覆蓋之前保存的所有示例? – user1893354

0

我會建議你使用一個庫像異步在一步步地保存操作執行這樣。按照這種方法進行的代碼更好的可讀性和更好的結果

var async = require('async'); 
router.post('/jobs', function(req, res, next) { 
    var job = new Job(req.body.jobDetails); 
    var examples = req.body.examples; 
    var savedExamples = []; 

    console.log("JOB DETAILS"); 
    console.log(req.body.jobDetails); 

    console.log("EXAMPLES"); 
    console.log(req.body.examples); 

    async.eachSeries(examples, function iteratee(example, callback) { 
     var eg = new Example({ 
      content: example 
     }); 
     eg.job = job; 
     eg.save(function(err, savedEg) { 
      if(!err) { 
      savedExamples.push(savedEg); 
      } 
      callback(err) 
     }); 
    }, function(err) { 
     if(err) { 
      //handle errors 
     } 
     job.examples = savedExamples; 
     job.save(function(err,job) { 
      if(err) { 
       //handle errors 
      } 
      //success callback 
     }); 
    }); 
}); 

使用這種方法,你將有其他所有操作完成後,只能調用一次作業保存功能。如果在任何時候觸發錯誤,則整個流程停止。有關異步庫的更多信息,請參閱this