Embora seu código não lide com alguns casos de erro e use o
find
errado função, o fluxo geral é típico dando o trabalho que você quer fazer. - Se houver erros além da duplicata, o retorno de chamada não será chamado, o que provavelmente causará problemas de downstream em seu aplicativo NodeJs
- use
findOne
em vez defind
pois haverá apenas um resultado, dado que a chave é única. Caso contrário, ele retornará uma matriz. - Se seu retorno de chamada esperava o tradicional
error
como o primeiro argumento, você pode passar diretamente o retorno de chamada para ofindOne
função em vez de introduzir uma função anônima. - Você também pode consultar
findOneAndUpdate
eventualmente, dependendo de qual será seu esquema e lógica finais.
Como mencionado, você pode usar
findOneAndUpdate
, mas com custo 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);
}
Ainda há um retorno de chamada, é claro, mas ele gravará os dados novamente se a duplicata for encontrada. Se isso é um problema realmente depende dos casos de uso.
Fiz uma pequena limpeza no seu código... mas é bem simples e o retorno de chamada deve estar claro. O
callback
para a função sempre recebe o documento recém-salvo ou aquele que foi correspondido como duplicado. É responsabilidade da função que chama saveNewValue
para verificar se há um erro e tratá-lo adequadamente. Você verá como também garanti que o retorno de chamada seja chamado independentemente do tipo de erro e sempre seja chamado com o resultado de maneira consistente. 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);
});
}
Como alternativa, você pode usar a promessa padronizar. Este exemplo está usando 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
});