Докато вашият код не обработва няколко случая на грешка и използва грешно find
функция, общият поток е типичен за работата, която искате да свършите.
- Ако има грешки, различни от дубликата, обратното извикване не се извиква, което вероятно ще причини проблеми надолу по веригата във вашето приложение NodeJs
- използвайте
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);
}
Все още има обратно извикване, разбира се, но то ще запише данните отново, ако бъде намерен дубликат. Дали това е проблем наистина зависи от случаите на употреба.
Направих малко почистване на вашия код... но той наистина е доста прост и обратното извикване трябва да е ясно. 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);
});
}
Като алтернатива можете да използвате обещание модел. Този пример използва 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
});