Sebbene il tuo codice non gestisca alcuni casi di errore e utilizzi il find
errato funzione, il flusso generale è tipico dando il lavoro che vuoi fare.
- Se sono presenti errori diversi dal duplicato, il callback non viene chiamato, il che probabilmente causerà problemi a valle nell'applicazione NodeJs
- usa
findOne
invece difind
poiché ci sarà un solo risultato dato che la chiave è unica. In caso contrario, restituirà un array. - Se la tua richiamata prevedeva il tradizionale
error
come primo argomento, puoi passare direttamente la callback afindOne
funzione piuttosto che introdurre una funzione anonima. - Potresti anche dare un'occhiata a
findOneAndUpdate
alla fine, a seconda di quale sarà lo schema e la logica finali.
Come accennato, potresti essere in grado di utilizzare findOneAndUpdate
, ma con un costo aggiuntivo.
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);
}
C'è ancora una richiamata ovviamente, ma scriverà di nuovo i dati se viene trovato il duplicato. Il fatto che si tratti di un problema dipende davvero dai casi d'uso.
Ho fatto una piccola pulizia del tuo codice... ma è davvero abbastanza semplice e il callback dovrebbe essere chiaro. Il callback
alla funzione riceve sempre o il documento appena salvato o quello che è stato abbinato come duplicato. È responsabilità della funzione che chiama saveNewValue
per verificare la presenza di un errore e gestirlo correttamente. Vedrai come ho anche assicurato che il callback venga chiamato indipendentemente dal tipo di errore e venga sempre chiamato con il risultato in modo coerente.
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);
});
}
In alternativa, puoi utilizzare promise modello. Questo esempio utilizza 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
});