Si bien su código no maneja algunos casos de error y usa el find
incorrecto función, el flujo general es típico dando el trabajo que desea hacer.
- Si hay otros errores además del duplicado, no se llama a la devolución de llamada, lo que probablemente cause problemas posteriores en su aplicación NodeJs
- use
findOne
en lugar defind
ya que solo habrá un resultado dado que la clave es única. De lo contrario, devolverá una matriz. - Si su devolución de llamada esperaba el tradicional
error
como primer argumento, puede pasar directamente la devolución de llamada afindOne
función en lugar de introducir una función anónima. - También puede consultar
findOneAndUpdate
eventualmente, dependiendo de cuál será su esquema y lógica finales.
Como se mencionó, es posible que pueda usar findOneAndUpdate
, pero con costo adicional.
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);
}
Todavía hay una devolución de llamada, por supuesto, pero volverá a escribir los datos si se encuentra el duplicado. Si eso es un problema realmente depende de los casos de uso.
He realizado una pequeña limpieza de su código... pero en realidad es bastante simple y la devolución de llamada debería ser clara. La callback
a la función siempre recibe el documento recién guardado o el que coincidió como un duplicado. Es responsabilidad de la función que llama a saveNewValue
para verificar si hay un error y manejarlo adecuadamente. Verá cómo también me aseguré de que la devolución de llamada se llame independientemente del tipo de error y siempre se llame con el resultado de manera coherente.
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);
});
}
Alternativamente, puede usar la promesa patrón. Este ejemplo usa 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
});