Hoewel je code een paar foutgevallen niet afhandelt en de verkeerde find
gebruikt, functie, de algemene stroom is typisch voor het werk dat u wilt doen.
- Als er andere fouten zijn dan het duplicaat, wordt de callback niet aangeroepen, wat waarschijnlijk downstream-problemen zal veroorzaken in uw NodeJs-toepassing
- gebruik
findOne
in plaats vanfind
aangezien er maar één resultaat zal zijn, aangezien de sleutel uniek is. Anders wordt een array geretourneerd. - Als je terugbelt de traditionele
error
als eerste argument zou je de callback direct kunnen doorgeven aan defindOne
functie in plaats van een anonieme functie te introduceren. - Misschien wil je ook kijken naar
findOneAndUpdate
uiteindelijk, afhankelijk van wat je uiteindelijke schema en logica zal zijn.
Zoals vermeld, kunt u mogelijk findOneAndUpdate
. gebruiken , maar met extra kosten.
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);
}
Er is natuurlijk nog steeds een callback, maar het zal de gegevens opnieuw schrijven als het duplicaat wordt gevonden. Of dat een probleem is, hangt echt af van de gebruikssituaties.
Ik heb je code een beetje opgeschoond... maar het is echt heel eenvoudig en de terugroepactie zou duidelijk moeten zijn. De callback
naar de functie ontvangt altijd ofwel het nieuw opgeslagen document of het document dat als een duplicaat is gekoppeld. Het is de verantwoordelijkheid van de functie die saveNewValue
. aanroept om te controleren op een fout en deze correct af te handelen. Je zult zien hoe ik er ook voor heb gezorgd dat de callback wordt aangeroepen, ongeacht het type fout en altijd op een consistente manier wordt aangeroepen met het resultaat.
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);
});
}
Als alternatief kunt u de belofte gebruiken patroon. Dit voorbeeld gebruikt 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
});