Sie müssten Ihre Aufrufe verschachteln, um die Produkt-ID aus dem anderen Modell zu entfernen. Zum Beispiel in Ihrem Aufruf, das Produkt aus Product
zu entfernen Sammlung, könnten Sie auch einen weiteren Aufruf tätigen, um die Referenz aus dem Partner
zu entfernen model innerhalb des Ergebnis-Callbacks. Wenn Sie das Produkt standardmäßig entfernen, werden seine Verweise auf die Campaign
entfernt Modell.
Der folgende Code zeigt die obige Intuition:
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);
}
);
});
});
Um die zugehörigen Kampagnen zu entfernen, benötigen Sie möglicherweise einen zusätzlichen Entfernungsvorgang, der die zugehörige Kampagnen-ID für eine bestimmte Produkt-ID übernimmt. Betrachten Sie den folgenden schmutzigen Hack, der Ihnen möglicherweise ein One-Way-Ticket in die Callback-Hölle einbringt wenn man nicht aufpasst mit der Callback-Verschachtelung:
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);
})
}
);
}
);
});
Obwohl es funktioniert, kann der obige potenzielle Fallstrick vermieden werden, indem async/await oder async
Bibliothek. Aber zuerst, um Ihnen ein besseres Verständnis für die Verwendung mehrerer Rückrufe mit dem async
veranschaulichen wir dies anhand eines Beispiels aus Seven Dinge, die Sie mit Node.js nicht mehr tun sollten
von mehreren Operationen mit Rückrufen, um eine übergeordnete Entität zu finden, und dann untergeordnete Entitäten zu finden, die der übergeordneten gehören:
methodA(function(a){
methodB(function(b){
methodC(function(c){
methodD(function(d){
// Final callback code
})
})
})
})
Mit async/await werden Ihre Aufrufe als
strukturiert umstrukturiertrouter.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
}
})
Mit dem async-Modul können Sie entweder die series-Methode verwenden, um die Verwendung von Rückrufen zum Verschachteln von Code mehrerer Methoden zu adressieren, was zu Callback Hell :
Reihe :
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
}
)
Oder der Wasserfall :
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'
}
)
Kehren Sie nun zu Ihrem Code zurück und verwenden Sie die asynchrone Wasserfallmethode, mit der Sie Ihren Code dann umstrukturieren könnten
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
});
});