我有一个具有多个功能的 api 调用。除了对每个方法都应用错误处理之外,是否可以使用将错误发送给 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);
            });
        };
    };
});