dop*_*man 13 mongoose mongodb node.js
这是我的代码:
var thisValue = new models.Value({
id:id,
title:title //this is a unique value
});
console.log(thisValue);
thisValue.save(function(err, product, numberAffected) {
if (err) {
if (err.code === 11000) { //error for dupes
console.error('Duplicate blocked!');
models.Value.find({title:title}, function(err, docs)
{
callback(docs) //this is ugly
});
}
return;
}
console.log('Value saved:', product);
if (callback) {
callback(product);
}
});
Run Code Online (Sandbox Code Playgroud)
如果我检测到正在尝试插入重复项,我会阻止它.但是,当发生这种情况时,我想返回现有文档.正如你所看到的,我已经实现了一串回调,但这是丑陋的,它是不可预测的(即我怎么知道将调用哪个回调?我如何传递正确的回调?).有谁知道如何解决这个问题?任何帮助赞赏.
Wir*_*rie 18
虽然您的代码不处理一些错误情况,并且使用了错误的find
函数,但一般流程通常会给您想要的工作.
findOne
而不是find
只有一个结果.否则,它将返回一个数组.error
作为第一个参数,你可以直接将回调传递给findOne
函数而不是引入匿名函数.findOneAndUpdate
,具体取决于您的最终架构和逻辑.如上所述,您可以使用findOneAndUpdate
,但需要额外费用.
function save(id, title, callback) {
Value.findOneAndUpdate(
{id: id, title: title}, /* query */
{id: id, title: title}, /* update */
{ upsert: true}, /* create if it doesn't exist */
callback);
}
Run Code Online (Sandbox Code Playgroud)
当然还有一个回调,但如果发现重复,它会再次写入数据.这是一个问题是否真的取决于用例.
我已经对你的代码进行了一些清理......但它确实很简单,回调应该很清楚.在callback
该函数总是收到任何新保存的文档或被匹配为重复的一个.调用函数调用saveNewValue
错误并正确处理它是责任.您将看到我如何确定无论错误类型如何都会调用回调,并始终以一致的方式调用结果.
function saveNewValue(id, title, callback) {
if (!callback) { throw new Error("callback required"); }
var thisValue = new models.Value({
id:id,
title:title //this is a unique value
});
thisValue.save(function(err, product) {
if (err) {
if (err.code === 11000) { //error for dupes
return models.Value.findOne({title:title}, callback);
}
}
callback(err, product);
});
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用promise模式.这个例子是使用when.js.
var when = require('when');
function saveNewValue(id, title) {
var deferred = when.defer();
var thisValue = new models.Value({
id:id,
title:title //this is a unique value
});
thisValue.save(function(err, product) {
if (err) {
if (err.code === 11000) { //error for dupes
return models.Value.findOne({title:title}, function(err, val) {
if (err) {
return deferred.reject(err);
}
return deferred.resolve(val);
});
}
return deferred.reject(err);
}
return deferred.resolve(product);
});
return deferred.promise;
}
saveNewValue('123', 'my title').then(function(doc) {
// success
}, function(err) {
// failure
});
Run Code Online (Sandbox Code Playgroud)
Leo*_*tny 10
我非常喜欢WiredPrairie的答案,但他的承诺实施过于复杂.
所以,我决定添加自己的promise实现.
3.8.x
如果您使用的是最新的Mongoose,3.8.x
那么就不需要使用任何其他promise模块,因为3.8.0
model .create()
方法会返回一个promise:
function saveNewValue(id, title) {
return models.Value.create({
id:id,
title:title //this is a unique value
}).then(null, function(err) {
if (err.code === 11000) {
return models.Value.findOne({title:title}).exec()
} else {
throw err;
}
});
}
saveNewValue('123', 'my title').then(function(doc) {
// success
console.log('success', doc);
}, function(err) {
// failure
console.log('failure', err);
});
Run Code Online (Sandbox Code Playgroud)
models.Value.findOne({title:title}).exec()
也返回一个promise,因此不需要回调或任何额外的转换.
如果你通常不在你的代码中使用promises,这里是它的回调版本:
function saveNewValue(id, title, callback) {
models.Value.create({
id:id,
title:title //this is a unique value
}).then(null, function(err) {
if (err.code === 11000) {
return models.Value.findOne({title:title}).exec()
} else {
throw err;
}
}).onResolve(callback);
}
Run Code Online (Sandbox Code Playgroud)
如果您之前使用的是任何Mongoose版本3.8.0
,那么您可能需要when
模块的一些帮助:
var when = require('when'),
nodefn = require('when/node/function');
function saveNewValue(id, title) {
var thisValue = new models.Value({
id:id,
title:title //this is a unique value
});
var promise = nodefn.call(thisValue.save.bind(thisValue));
return promise.spread(function(product, numAffected) {
return product;
}).otherwise(function(err) {
if (err.code === 11000) {
return models.Value.findOne({title:title}).exec()
} else {
throw err;
}
});
}
Run Code Online (Sandbox Code Playgroud)
我正在使用nodefn.call
辅助函数将回调式.save()
方法转换为promise.Mongoose团队承诺在其中添加承诺支持Mongoose 4.x
.
然后我使用.spread
helper方法从.save()
回调中提取第一个参数.
归档时间: |
|
查看次数: |
11432 次 |
最近记录: |