Även om din kod inte hanterar några felfall och använder fel find
funktion, är det allmänna flödet typiskt för det arbete du vill göra.
- Om det finns andra fel än dubbletten, anropas inte återuppringningen, vilket sannolikt kommer att orsaka nedströmsproblem i din NodeJs-applikation
- använd
findOne
istället för attfind
eftersom det bara blir ett resultat givet att nyckeln är unik. Annars kommer den att returnera en array. - Om din återuppringning förväntade sig det traditionella
error
som det första argumentet kan du skicka återuppringningen direkt tillfindOne
funktion snarare än att införa en anonym funktion. - Du kanske också vill titta på
findOneAndUpdate
så småningom, beroende på vad ditt slutliga schema och logik kommer att bli.
Som nämnts kanske du kan använda findOneAndUpdate
, men med extra kostnad.
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);
}
Det finns naturligtvis fortfarande en återuppringning, men den kommer att skriva data igen om dubbletten hittas. Huruvida det är ett problem beror verkligen på användningsfall.
Jag har rensat lite i din kod... men det är egentligen ganska enkelt och återuppringningen borde vara tydlig. callback
till funktionen får alltid antingen det nyligen sparade dokumentet eller det som matchades som en dubblett. Det är funktionen som anropar saveNewValue
s ansvar för att leta efter ett fel och hantera det korrekt. Du kommer att se hur jag också har sett till att återuppringningen anropas oavsett typ av fel och alltid anropas med resultatet på ett konsekvent sätt.
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);
});
}
Alternativt kan du använda löftet mönster. Det här exemplet använder 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
});