我是nodejs的初学者,我遇到了一些我不理解的回调行为。我使用Express路由器使用POST请求将Mongoose对象写入Mongodb。在请求的主体中,我传递了一个嵌套的json结构,其中包含两个字段 - jobDetails
和examples
。 jobDetails
中的数据用于创建Job
Mongoose对象,examples
中的数据用于创建多个Example
Mongoose对象。 Job
和Example
个对象的链接是Job
在其中一个字段中包含Example
个对象的列表。
我尝试实现此方法的方法是以下列方式进行回调。基本上我首先将Job
对象保存到mongo,然后迭代示例 - 每次创建一个Example
对象并通过.job
字段将其链接到作业,同时保存{{ 1}}对象到mongo。然后在回调Example
对象保存功能时,我使用新的Example
对象更新了Job
对象,并将更新后的版本保存到mongo。
Example
这没有像我预期的那样发挥作用。具体来说,实际保存到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);
});
}
});
我也不确定这是否也是最佳解决方案。但我想知道为什么我的原始方法导致了意想不到的行为。
答案 0 :(得分: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);
});
}
}
});
});
答案 1 :(得分:0)
我建议您使用像async这样的库来逐步执行此类保存操作。遵循此方法以提高代码的可读性和更好的结果
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!