Ответ 1
Пока ваш код не обрабатывает несколько ошибок и использует неправильную функцию 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);
});
}
В качестве альтернативы вы можете использовать шаблон 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
});