Vous devrez imbriquer vos appels pour supprimer l'identifiant du produit de l'autre modèle. Par exemple, dans votre appel pour supprimer le produit du Product
collection, vous pouvez également effectuer un autre appel pour supprimer la référence du Partner
modèle dans le rappel des résultats. La suppression du produit par défaut supprimera ses références à la Campaign
Modèle.
Le code suivant montre l'intuition ci-dessus :
var campSchema = require('../model/camp-schema');
router.post('/removeProduct', function (req, res) {
campSchema.Product.findOneAndRemove({ _id: req.body.productId }, function (err, response) {
if (err) throw err;
campSchema.Partner.update(
{ "products": req.body.productId },
{ "$pull": { "products": req.body.productId } },
function (err, res){
if (err) throw err;
res.json(res);
}
);
});
});
Pour supprimer les campagnes associées, vous aurez peut-être besoin d'une opération de suppression supplémentaire qui prend l'identifiant de campagne associé d'un identifiant de produit donné. Considérez le hack sale suivant qui peut potentiellement vous attribuer un aller simple vers callback hell sinon attention à l'imbrication des rappels :
router.post('/removeProduct', function (req, res) {
campSchema.Product.findOneAndRemove(
{ _id: req.body.productId },
{ new: true },
function (err, product) {
if (err) throw err;
campSchema.Partner.update(
{ "products": req.body.productId },
{ "$pull": { "products": req.body.productId } },
function (err, res){
if (err) throw err;
var campaignList = product.campaign
campSchema.Campaign.remove({ "_id": { "$in": campaignList } })
.exec(function (err, res){
if (err) throw err;
res.json(product);
})
}
);
}
);
});
Bien que cela fonctionne, le piège potentiel ci-dessus peut être évité en utilisant async/await ou le async
bibliothèque. Mais d'abord, pour vous donner une meilleure compréhension de l'utilisation de plusieurs rappels avec le async
module, illustrons cela avec un exemple de Seven Ce que vous devriez arrêter de faire avec Node.js
de plusieurs opérations avec des rappels pour trouver une entité parente, puis recherchez les entités enfants qui appartiennent au parent :
methodA(function(a){
methodB(function(b){
methodC(function(c){
methodD(function(d){
// Final callback code
})
})
})
})
Avec async/wait, vos appels seront restructurés en
router.post('/removeProduct', async (req, res) => {
try {
const product = await campSchema.Product.findOneAndRemove(
{ _id: req.body.productId },
{ new: true }
)
await campSchema.Partner.update(
{ "products": req.body.productId },
{ "$pull": { "products": req.body.productId } }
)
await campSchema.Campaign.remove({ "_id": { "$in": product.campaign } })
res.json(product)
} catch(err) {
throw err
}
})
Avec le module async, vous pouvez soit utiliser la méthode de série pour traiter l'utilisation de rappels pour imbriquer le code de plusieurs méthodes qui peuvent entraîner L'enfer des rappels :
Séries :
async.series([
function(callback){
// code a
callback(null, 'a')
},
function(callback){
// code b
callback(null, 'b')
},
function(callback){
// code c
callback(null, 'c')
},
function(callback){
// code d
callback(null, 'd')
}],
// optional callback
function(err, results){
// results is ['a', 'b', 'c', 'd']
// final callback code
}
)
Ou la cascade :
async.waterfall([
function(callback){
// code a
callback(null, 'a', 'b')
},
function(arg1, arg2, callback){
// arg1 is equals 'a' and arg2 is 'b'
// Code c
callback(null, 'c')
},
function(arg1, callback){
// arg1 is 'c'
// code d
callback(null, 'd');
}], function (err, result) {
// result is 'd'
}
)
Revenons maintenant à votre code, en utilisant la méthode de cascade asynchrone, vous pouvez ensuite restructurer votre code pour
router.post('/removeProduct', function (req, res) {
async.waterfall([
function (callback) {
// code a: Remove Product
campSchema.Product.findOneAndRemove(
{ _id: req.body.productId },
function (err, product) {
if (err) callback(err);
callback(null, product);
}
);
},
function (doc, callback) {
// code b: Remove associated campaigns
var campaignList = doc.campaign;
campSchema.Campaign
.remove({ "_id": { "$in": campaignList } })
.exec(function (err, res) {
if (err) callback(err);
callback(null, doc);
}
);
},
function (doc, callback) {
// code c: Remove related partner
campSchema.Partner.update(
{ "products": doc._id },
{ "$pull": { "products": doc._id } },
function (err, res) {
if (err) callback(err);
callback(null, doc);
}
);
}
], function (err, result) {
if (err) throw err;
res.json(result); // OUTPUT OK
});
});