Du skulle behöva kapsla dina samtal för att ta bort produkt-id:t från den andra modellen. Till exempel i ditt samtal om att ta bort produkten från Produkt
samling, kan du också ringa ett annat samtal för att ta bort referensen från Partner
modell inom resultatet callback. Om du tar bort produkten som standard tas dess referenser till Kampanjen
bort Modell.
Följande kod visar intuitionen ovan:
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);
}
);
});
});
För att ta bort de associerade kampanjerna kan du behöva en extra borttagningsåtgärd som tar in det associerade kampanj-id från ett givet produkt-id. Tänk på följande smutsiga hack som potentiellt kan ge dig en enkelbiljett till återuppringningshelvetet om du inte är försiktig med återuppringning:
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);
})
}
);
}
);
});
Även om det fungerar, kan ovanstående potentiella fallgrop undvikas genom att använda async/await eller async
bibliotek. Men först, för att ge dig en bättre förståelse för hur du använder flera återuppringningar med async
modul, låt oss illustrera detta med ett exempel från Seven Saker du bör sluta göra med Node.js
av flera operationer med återuppringningar för att hitta en överordnad enhet och sedan hitta underordnade enheter som tillhör den överordnade:
methodA(function(a){
methodB(function(b){
methodC(function(c){
methodD(function(d){
// Final callback code
})
})
})
})
Med async/await omstruktureras dina samtal strukturerade som
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
}
})
Med asynkroniseringsmodulen kan du antingen använda seriemetoden för att adressera användningen av callbacks för kapslingskod för flera metoder, vilket kan resultera i Callback Hell :
Serie :
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
}
)
Eller vattenfallet :
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'
}
)
Går nu tillbaka till din kod, med den asynkrona vattenfallsmetoden kan du sedan omstrukturera din kod till
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
});
});