如何在node.js中使用全局error handling代码进行整个api调用

我有一个有多个function的API调用。 而不是应用每个方法的error handling,是否有可能使用全局error handling代码将错误发送给UI开发人员。

代码如下:

app.post('/billing/pricingdetails', function (req, res) { console.log('pricing api called'); var workload = req.body; var resourcelevelPricing = {}; var response = {}; var workloadinfo = { workloadId: workload.workloadId, ownerId: workload.ownerId, uniqueName: workload.uniqueName, name: workload.name } var pricing = {} var allresourceIdentifiers; if (workload.elements && workload.elements.length > 0) { var elementlevelpricingSummary = {}; var elementArray = []; var allresourceIdentifierArray = []; var elementinfo = {}; var metadataModified = {}; var elementsParam = workload.elements; // handle configurable resource var configurableElementarray = []; // create array of all the elements in workloadjson - to be used for resourcelevel (instance/image), charamountunitlevel, resourcetypelevel pricing detail for (var index in elementsParam) { // if condition skips the uri of configurable resources - handle configurable resource if(!elementsParam[index].parameters.ResourceParameters) { allresourceIdentifierArray.push(elementsParam[index].uri); if (elementsParam[index].parameters.imageUri) { allresourceIdentifierArray.push(elementsParam[index].parameters.imageUri); } } } var allresourceIdentifiers = allresourceIdentifierArray.join(','); // call the functionalities that gives the each level of pricing detail synchronously to construct the workload json async.series([ function (callback) { getpricingSummary(elementsParam, function (err, workloadinfo) { if(err){ } else { callback(null, workloadinfo); } }); }, function (callback) { getPricingforResourceIdentifiers(allresourceIdentifiers, function (err, pricingDetail) { pricing.resourceLevel = pricingDetail; callback(null, pricingDetail); }); }, function (callback) { getchargeamountunitlevelPricing(allresourceIdentifiers, function (err, pricingDetail) { //merge configurable resource with concrete resource pricing details - handle configurable resource if(configurableElementarray.length > 0) { var concatednatedArray = pricingDetail.concat(configurableElementarray); var finalResult = []; var i = concatednatedArray.reduce(function (result, o) { var key = o.chargeAmountUnit + o.currencyCode; if (!(key in result)) { result.arr.push(result[key] = o); finalResult.push(result); } else { result[key].chargeAmount += Number(o.chargeAmount); } return result; }, { arr: [] }).arr; pricing.chargeamountunitLevel = i; trace.info(i); } else { pricing.chargeamountunitLevel = pricingDetail; } callback(null, pricingDetail); }); }, function (callback) { getresourcetypelevelPricing(allresourceIdentifiers, function (err, pricingDetail) { if(configurableElementarray.length > 0) { var concatednatedArray = pricingDetail.concat(configurableElementarray); var i = concatednatedArray.reduce(function (result, o) { var key = o.chargeAmountUnit + o.currencyCode + o.Name; if (!(key in result)) { result.arr.push(result[key] = o); } else { result[key].chargeAmount += o.chargeAmount; } return result; }, { arr: [] }).arr; pricing.resourcetypeLevel = i; trace.info(i); } else { pricing.resourcetypeLevel = pricingDetail; } callback(null, pricingDetail); }); } ], function (err, result) { workloadinfo.pricing = pricing; res.send(workloadinfo); }); // get element level pricing summary for each elements (vm/vs) in the array within workload json - the output to be appended within metadata of workload json function getpricingSummary(elementsParam, callback) { async.forEachSeries(elementsParam, createResponse, function (err,result) { return callback(null, result); }); }; // this method called by async.forEachSeries passing each elements (vm/vs) of workload function createResponse(elements, callback) { var resourceIdentifierArray = []; elementinfo = elements; resourceIdentifierArray.push(elements.uri); if (elements.parameters.imageUri) { resourceIdentifierArray.push(elements.parameters.imageUri); } // build string of resourceIdentifier (instance/image) for input element var resourceIdentifiers = resourceIdentifierArray.join(','); console.log(resourceIdentifiers); if(elements.parameters.ResourceParameters) { trace.info('1'); trace.info(elements.parameters.ResourceParameters); var configJson = JSON.parse(elements.parameters.ResourceParameters); trace.info(Number(configJson.cpuCount)); metadataModified = elements.metadata; // TODO : Remove this hard-coding elementlevelpricingSummary.Name = 'Hardware'; if(configJson.totalUnitPrice) { var chargeAmount = configJson.totalUnitPrice; elementlevelpricingSummary.chargeAmount = Math.round(chargeAmount * 100)/100; } if(configJson.ChargeAmountUnit) { var chargeAmountUnit = configJson.ChargeAmountUnit; elementlevelpricingSummary.chargeAmountUnit = configJson.ChargeAmountUnit; } if(configJson.CurrencyCode) { var currencyCode = configJson.CurrencyCode; elementlevelpricingSummary.currencyCode = configJson.CurrencyCode; } metadataModified.pricingSummary = elementlevelpricingSummary; configurableElementarray.push(elementlevelpricingSummary); // delete original metadata from workload json (to be replaced by metadata containing pricing summary) delete elementinfo.metadata; elementinfo.metadata = metadataModified; elementArray.push(elementinfo); // global workloadinfo variable is appended with array of elements with its pricing summary within metadata of respective elements workloadinfo.elements = elementArray; return callback(); } else { // Get element level pricing summary mysql.elementlevelpricing(resourceIdentifiers, conn, function (result) { elementlevelpricingSummary = result; metadataModified = elements.metadata; metadataModified.pricingSummary = elementlevelpricingSummary; // delete original metadata from workload json (to be replaced by metadata containing pricing summary) delete elementinfo.metadata; elementinfo.metadata = metadataModified; elementArray.push(elementinfo); // global workloadinfo variable is appended with array of elements with its pricing summary within metadata of respective elements workloadinfo.elements = elementArray; return callback(null,workloadinfo); }); } }; function getPricingforResourceIdentifiers(resourceIdentifiers, callback) { mysql.pricingDetail(resourceIdentifiers, conn, function (result) { return callback(null, result); }); }; function getchargeamountunitlevelPricing(resourceIdentifiers, callback) { mysql.chargeamountunitlevelPricing(resourceIdentifiers, conn, function (result) { return callback(null, result); }); }; function getresourcetypelevelPricing(resourceIdentifiers, callback) { mysql.resourcetypelevelPricing(resourceIdentifiers, conn, function (result) { return callback(null, result); }); }; }; }); 

使用Express,您可以安装一个error handling程序,当您的任何路由发生错误时将会调用该error handling程序:

 // somewhere at the end of your middleware/route chain app.use(function(err, req, res, next) { res.send(500, err.message); // or whatever you want to send back }); 

重新抛出代码中发生的任何错误仍然是最好的:

 if (err) throw err; 

另外,由于您使用的是async ,所以您始终可以将错误传播回去:

 if (err) return callback(err); 

并处理最后callback中的错误。