Как подойти к этому сценарию в асинхронном программировании / узел js
Я пишу сервис в nodejs. Пожалуйста, прочитайте ниже подход, который я делаю, чтобы решить эту проблему.
Сначала я вызываю конечную точку отдыха (скажем / предложения) для получения данных. скажи это cloudSenseData
Окончательный ответ Мне нужно помассировать / манипулировать данными, чтобы выдать нужный ответ в качестве вывода.
Во время массирования данных (звонок сверху) я должен проверить, есть ли информация о соответствующем продукте.
если он присутствует, мне нужно вызвать другую конечную точку отдыха (скажем / предложения /: идентификатор / продукты):id - это каталогизатор, полученный при предыдущем вызове (cloudSenseData), чтобы получить более подробную информацию о товаре, которую я могу включить в окончательный вывод в массаж.
Итак, скажем, в cloudSenseData у меня есть 10 элементов каталога.
Вот шаги, которые я делаю во время массирования данных:
- Использование async.map для cloudSenseData и сопоставление его с нужным форматом ответа (я использовал его для параллельной работы), а также функция обратного вызова, выполняющая эту задачу
- В обратном вызове, когда я делаю ответ по мере необходимости, я проверяю, имеет ли он информацию relatedProduct, если у него нет проблем, иначе я вызываю конечную точку нисходящего потока, чтобы получить больше relatedProductInfo, используя catologueItemId.(Здесь я использую deasync)
Это занимает больше времени, чем нужно.
Может кто-нибудь предложить какие-либо альтернативы, чтобы приблизиться к этому?
Обновление с помощью кода: common-nodejs - это библиотека, которую мы написали, которая объединяет многие функции, такие как вызов остальных конечных точек с помощью restify, чтение конфигурации приложения и многие другие. Код ниже приведен в машинописном тексте. Надеюсь это поможет.
import {log,serviceInfo,HttpMethod} from "common-nodejs";
import { CloudsenseBaasJsonAction } from './cloudsense-baas-connector';
import {Constants} from "./Constants";
let request = require('request');
let deasync = require('deasync');
let moment = require("moment");
let async= require("async");
let PropertiesReader = require("properties-reader");
let endpointsConfigFile = require("../../config/endpoints.json");
//load the properties file to map the cloudsense attributes with required keys.
let parseConfig=new PropertiesReader("config/fields_config.properties");
// helper method in adding more details in response by reading the properties file
export let parsePropertiesFile = function(attribute,microserviceResponse,key,value){
let cloudSenseKey = attribute[key];
let microServiceKey = parseConfig.get(cloudSenseKey);
//console.log("********cloudSenseKey***************",cloudSenseKey,"************ microServiceKey***" ,microServiceKey);
if( microServiceKey!= undefined && microServiceKey!=null){
// console.log("********microServiceKey***************",microServiceKey ,attribute[value]);
microserviceResponse[microServiceKey] = attribute[value];
}
};
// this method does the fetching the detailed info if relatedProducts are there
export let requestRelatedProductsInfo = function(offerId):any{
// console.log("****************Above to Parse*******");
let body={};
let cloudsenseBaasJsonAction = new CloudsenseBaasJsonAction(HttpMethod.GET, body, '');
let sendRequestForRelatedProducts = deasync(function(callback){
request({
proxy: serviceInfo.extras.internetProxy,
url: serviceInfo.extras.serviceCloudsense.apiEndpoint+"/services/current/offer/"+offerId+"/products",
method: endpointsConfigFile.cloudsense_baas.offers.method,
headers: cloudsenseBaasJsonAction.modifyHeadersWithParams({
"csTime": Date.now(),
"method": HttpMethod[endpointsConfigFile.cloudsense_baas.offers.method],
"path": "/services/current/offer/"+offerId+"/products",
"clientKey": serviceInfo.extras.serviceCloudsense.clientKey,
"clientSecret": serviceInfo.extras.serviceCloudsense.clientSecret
})
},function (err, res, body) {
if(res.statusCode==404 || res.statusCode==500){
console.log("********res***offerId*************",res.statusCode,offerId);
}
if(err){
// console.log("*****************Errors****************",err);
callback(err,null);
}
callback(null,body);
});
});
return JSON.parse(sendRequestForRelatedProducts());
}
export class Parser {
/*
* This method is used to massage the cloudsense data and respond with the below formate
*
* {
* "catalogueId": "a26O0000000SOS7IAO",
* "price": 1536,
* "name": "IPHONE 6S PLUS",
* "default": "true",
* "color": "Silver",
* "memory": "128GB",
* "contentId": "IPHONE6S128GBSILVER",
* "featured": "true",
* "isOutright": "Outright",
* "brand": "Apple",
* "startdate": "01-09-2016",
* "enddate": "01-09-2017",
* "OS": "iOS",
* "bluetick": true
* }
*
*
*/
public parseCloudsenseData(CloudsenseData:any,isDefaultFlow : boolean):any{
console.log('*******isDefaultFlow********',isDefaultFlow);
let current_Date = moment().format(Constants.DateFormate);
let parseCloudData = function(result,callback){
try{
let microserviceResponse={
"catalogueId" : result.catalogueId,
"catalogueItemId" : result.catalogueItemId,
"outrightPrice" : result.cscfga__One_Off_Charge__c,
"displayName" : result.name,
"currentDate" : current_Date,
"recurringPrice" : result.cscfga__Recurring_Charge__c
};
let key = Constants.Name;
let value = Constants.Value;
//fetch the list of attributes.
for(let att of result.attributes){
parsePropertiesFile(att,microserviceResponse,key,value);
}
debugger;
//fetching the relatedProducts Data. if there are relatedProducts calling the endpoint to get more details
if(!isDefaultFlow && result.relatedProducts!= undefined && result.relatedProducts!=null && result.relatedProducts.length>0 ){
let microserviceRelatedProductArray=[];
// debugger;
// result.catalogueItemId = 'caf71d86-bca3-4bed-a2d5-b233305b8e76'
let relatedProductArray = requestRelatedProductsInfo(result.catalogueItemId);
for(let relatedProduct of relatedProductArray.results){
// for(let relatedProduct of relatedProductArray){
let finalRelatedProduct ={
"productId" : relatedProduct.productId,
"name" : relatedProduct.name,
"sku" : relatedProduct.sku,
"productType" : relatedProduct.productType,
"productSubType" : relatedProduct.productSubType,
"outrightPrice" : relatedProduct.cscfga__One_Off_Charge__c,
"recurringPrice" : relatedProduct.cscfga__Recurring_Charge__c,
"contentId" : '',
"mobileRepaymnetOption":''
};
//This loop is there to find the content_id among available attributes dynamically.
for(let att of relatedProduct.attributes){
parsePropertiesFile(att,finalRelatedProduct,key,value);
}
microserviceRelatedProductArray.push(finalRelatedProduct);
} // end of for loop.
microserviceResponse.relatedProducts =microserviceRelatedProductArray;
}//end of if. ( view details flow).
// if(!isDefaultFlow && result.relatedProducts!= undefined && result.relatedProducts!=null && result.relatedProducts.length>0 ) {
// var catalogueItemIdArray = [];
// catalogueItemIdArray.push(result.catalogueId);
// }
return callback(null,microserviceResponse);
}catch(error){
// log.debug("************error block**********",error);
return callback(error,null);
}
};
let microServiceOutput;
//calling the parseCloudData method asynchronusly for each element in the array.
async.map(CloudsenseData.results, parseCloudData ,function (error,result){
if(error){
// console.log("***************Error***************",error);
microServiceOutput = {
"code":1005,
"message": "The downstream is not available"
};
return microServiceOutput;
}
microServiceOutput = result;
});
return microServiceOutput;
}//End of parseCloudsenseData();
}