Socket Hangup error in Nodejs for multiple API calls - node.js

I am trying to fetch a list of all companies listed in stock market from an external API, and after getting the list, I am trying to fetch all details regarding individual companies including graph data. It was all working fine. However, today I am getting socket hangup error. I have tried going through other posts here in stackoverflow. However, none of them works.
const request = require('request');
const fetchAPI = apiPath => {
return new Promise(function (resolve, reject) {
request(apiPath, function (error, response, body) {
if (!error && response.statusCode == 200) {
resolve(body);
} else {
reject(error);
}
});
});
}
// get list of all companies listed in
const fetchCompanyDetails = () => {
return new Promise(function (resolve, reject) {
let details = [];
fetchAPI('https://api//')
.then(res => {
res = JSON.parse(res)
details.push(res);
resolve(details);
})
.catch(err => {
console.log("error at fetchcompany details" + err);
})
});
}
const getDateAndPriceForGraphData = (graphData) => {
let res = []
graphData.forEach(data => {
let d = {}
d["x"] = new Date(data.businessDate).getTime() / 1000
d["y"] = data.lastTradedPrice
res.push(d)
})
return res
}
// get graph data for individual assets
const getGraphDataForAssets = (assetID) => {
return new Promise((resolve, reject) => {
let details = {};
fetchAPI(`https://api/${assetID}`)
.then(async (res) => {
res = JSON.parse(res)
let data = await getDateAndPriceForGraphData(res)
details = data
resolve(details);
})
.catch(err => {
console.log("error at getGraphDataForAssets" + err);
})
});
}
// fetch data about individual assets
const fetchAssetDetailsOfIndividualCompanies = (assetID) => {
return new Promise((resolve, reject) => {
let details = {"assetData" : {}, "graphData": {}};
fetchAPI(`https://api/${assetID}`)
.then(async (res1) => {
res1 = JSON.parse(res1)
details["assetData"] = res1
// get graph data
var graphData = await getGraphDataForAssets(assetID)
details["graphData"] = graphData
resolve(details);
})
.catch(err => {
console.log("error at fetchAssetDetailsOfIndividualCompanies" + err);
reject(err)
})
});
}
// returns list of details of all tradeable assets (Active and Suspended but not delisted)
const fetchDetailsForEachCompany = async (companyList) => {
let result = []
await Promise.all(companyList.map(async (company) => {
try {
// return data for active and suspended assets
if(company.status != "D") {
let companyData = await fetchAssetDetailsOfIndividualCompanies(company.id)
result.push(companyData)
}
} catch (error) {
console.log('error at fetchDetailsForEachCompany'+ error);
}
}))
return result
}
exports.fetchAssetDetails = async () => {
let companyDetails = await fetchCompanyDetails()
let det = await fetchDetailsForEachCompany(companyDetails[0])
return det
}

To expand on what I meant with not needing those new Promise()s, this would be an idiomatic async function refactoring for the above code.
I eliminated getGraphDataForAssets, since it was eventually not used; fetchAssetDetailsOfIndividualCompanies fetched the same data (based on URL, anyway), and then had getGraphDataForAssets fetch it again.
const request = require("request");
function fetchAPI(apiPath) {
return new Promise(function (resolve, reject) {
request(apiPath, function (error, response, body) {
if (!error && response.statusCode === 200) {
resolve(body);
} else {
reject(error);
}
});
});
}
async function fetchJSON(url) {
return JSON.parse(await fetchAPI(url));
}
async function fetchCompanyDetails() {
return [await fetchAPI("https://api//")];
}
function getDateAndPriceForGraphData(graphData) {
return graphData.map((data) => ({
x: new Date(data.businessDate).getTime() / 1000,
y: data.lastTradedPrice,
}));
}
// fetch data about individual assets
async function fetchAssetDetailsOfIndividualCompanies(assetID) {
const assetData = await fetchJSON(`https://api/${assetID}`);
const graphData = getDateAndPriceForGraphData(assetData);
return { assetID, assetData, graphData };
}
// returns list of details of all tradeable assets (Active and Suspended but not delisted)
async function fetchDetailsForEachCompany(companyList) {
const promises = companyList.map(async (company) => {
if (company.status === "D") return null;
return fetchAssetDetailsOfIndividualCompanies(company.id);
});
const results = await Promise.all(promises);
return results.filter(Boolean); // drop nulls
}
async function fetchAssetDetails() {
const companyDetails = await fetchCompanyDetails();
return await fetchDetailsForEachCompany(companyDetails[0]);
}
exports.fetchAssetDetails = fetchAssetDetails;

Related

Nodejs Function is returning undefined

I have 2 files index.js and models.js
my index.js file requires the model.js file
const models = require("./modules/models.js");
app.post('/message', (req, res) => {
const _lead = models.createLead(req.body)
_lead.then(l => {
console.log("resulted in lead", JSON.stringify(l))
// GETTING UNDEFINED HERE
})
// const _message = await models.createMessage(req.body.message)
res.send();
});
My models.js file has a functions that contain Promises
const createLead = async function (payload) {
// Find lead
let result
new Promise((resolve, reject) => {
findLeadById(payload.lead.rid).then(async _lead => {
// If a lead has not been found
if (!_lead) {
if(payload.companyRid != payload.lead.rid){
await db.collection('leads').add(payload.lead).then((l) => {
result = payload.lead
result['id'] = l.id
})
}
} else {
result = _lead
}
}).then(() => {
console.log(" result of create lead ",JSON.stringify(result))
resolve(result)
}).catch(error => {
error.log("reject", error)
reject(error)
})
})
}
const findLeadById = async function (lead) {
new Promise(async (resolve, reject) => {
const ref = db.collection('leads');
console.log("finding lead", JSON.stringify(lead))
await ref.where("rid", "==", lead).get().then((s) => {
let obj = null
if(s){
s.forEach(doc => {
console.log("found the lead in loop", JSON.stringify(doc.data()))
obj = doc.data()
obj['id'] = doc.id
})
}
resolve(obj)
}).catch(error => {
error.log("reject", error)
reject(error)
})
})
}
exports.createLead = createLead;
exports.findLeadById = findLeadById;
The model.js returns an object as expected
console.log(" result of create lead ",JSON.stringify(result))
However, I'm expecting to see that same object in the index.js in the then block but I'm getting undefined.
console.log("resulted in lead", JSON.stringify(l))
// GETTING UNDEFINED HERE
The following is not waiting for the associated functions to finish
const _lead = models.createLead(req.body)
I have also tried adding async and await which also didn't work
const _lead = await models.createLead(req.body).then(res => {console.log("result", res) // Still undefined
})
I think you can use resolve for any success response, and reject for error response. Ex:
await db.collection('leads').add(payload.lead).then((l) => {
let result = payload.lead
result['id'] = l.id
resolve(result)
})

Ec2 Instance Data Not pushed in array

I want to query all ec2 across regions.
I can log the data, but I can't push it to an array.
Here is the example
to loop over regions
let AWS = require('aws-sdk');
function regionConfig(reg) {
return new AWS.EC2({
region: reg
});
}
to list the allowed regions
const listRegions = async () => {
ec2 = regionConfig('eu-west-1')
let regionsArray = []
return await new Promise((resolve, reject) => {
ec2.describeRegions({}, function(err, data) {
if (err) reject(err, err.stack); // an error occurred
else {
for (let region of data.Regions) {
regionsArray.push(region.RegionName)
}
resolve(regionsArray)
}
});
})
}
to describe the ec2 instances
const describeIntances = async () => {
regions = await listRegions()
let instances = [];
return await new Promise((resolve, reject) => {
for(let i of regions) {
let ec2 = regionConfig(i)
ec2.describeInstances({}, function(err, data) {
if (err) reject(err, err.stack); // an error occurred
else {
let instances = [];
console.log(data)
for (let reservation of data.Reservations) {
instances.push(reservation)
}
resolve(instances)
}
})
}
})
}
execute the lambda
const handler = async (event) => {
const regions = await listRegions()
// console.log(regions)
const describeInstances = await describeIntances()
console.log(describeInstances)
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
handler()
I can see data for as many instances as I have, but when I push, the array is empty
could it be because of the async?

Getting infinite loop in firebase cloud function

I am using firestore to store the data in firebase. To get the count i am using cloud function. When i try to add / update / delete an entry in one collection it starts the infinite loop with another collection.
Example:
I am having a user table and agent table when i add/update/delete a user it should get updated in the agent table.
Though i have used separate functions for users and agent still i am getting an infinite loop.can anyone tell me how to resolve it
Query to update the user in user and agent table:
export const addUser = (values) =>
db
.collection('users')
.add(values)
.then((docRef) => {
let customer = { customer: {} };
customer.customer[docRef.id] = {
id: docRef.id,
name: values.name,
commission: values.agent.commission
};
let agentId = values.agent.id;
db.collection('agents')
.doc(agentId)
.set(customer, { merge: true });
});
Cloud function for user:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
exports = module.exports = functions.firestore
.document("users/{userUid}")
.onWrite(
(change, context) =>
new Promise((resolve, reject) => {
let dashboardId;
getDashboardId();
})
);
getDashboardId = () => {
admin.firestore().collection('dashboard').get().then((snapshot) => {
if (snapshot.size < 1) {
dashboardId = admin.firestore().collection('dashboard').doc().id;
} else {
snapshot.docs.forEach((doc) => {
dashboardId = doc.id;
});
}
return updateUser(dashboardId);
}).catch((error) => {
console.log('error is', error);
});
}
updateUser = (id) => {
admin.firestore().collection('users').where('isDeleted', '==', false).get().then((snap) => {
let usersData = {users: snap.size};
return admin.firestore().collection('dashboard').doc(id).set(usersData, {merge: true});
}).catch((error) => {
console.log('error is', error);
});
}
Cloud function for agent:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
exports = module.exports = functions.firestore
.document("agents/{agentUid}")
.onWrite(
(change, context) =>
new Promise((resolve, reject) => {
let dashboardId;
getDashboardId();
})
);
getDashboardId = () => {
admin.firestore().collection('dashboard').get().then((snapshot) => {
if (snapshot.size < 1) {
dashboardId = admin.firestore().collection('dashboard').doc().id;
} else {
snapshot.docs.forEach((doc) => {
dashboardId = doc.id;
});
}
return updateAgent(dashboardId);
}).catch((error) => {
console.log('error is', error);
});
}
updateAgent = (id) => {
admin.firestore().collection('agents').where('isDeleted', '==', false).get().then((snap) => {
let agentsData = {agents: snap.size};
return admin.firestore().collection('dashboard').doc(id).set(agentsData, {merge: true});
}).catch((error) => {
console.log('error is', error);
});
}

undefined result nodejs async await

i'm testing await functions but i have an "undefined" result when i check the return of the async function, my express function is like this (i removed unnecesary code, just to show how i am using the async
const getAppsConsumptionSum = async (msisdn, startPeriod, endPeriod) => {
var urlTigoPlus = 'http://...';
var args = {
requestConfig: {
timeout: config.get('localServer.remoteTimeout')
}
};
remoteApi = await restClient.get(url, args,
async (data, response) => {
if (response.statusCode === 200) {
sumatoria = await group(data.arrayofdata).by('subapplication').reduce(async function(id, entries) {
return {
appname: id,
mb: (entries.map(getBytes).reduce(add)) / 1048576
};
});
return sumatoria;
} else {
next(utils.error(503));
}
}
);
};
exports.dataAppsConsumption = async function(req, resp, next) {
let prepaidQuery = 'select ...';
const resultPrepaid = await clientDseDev.execute(prepaidQuery)
.then(async resultPrepaid => {
sumatoria = await getAppsConsumptionSum(variable1, startPeriod, endPeriod);
console.log('this variable shows undefined ' + sumatoria)
//i tried also with this
getAppsConsumptionSum(variable1, startPeriod, endPeriod).then((sumatoria) => {
console.log('this variable shows undefined ' + sumatoria)
});
})
.catch((err) => {
console.log(err)
});
};
thanks all for your help, #jfriend00 solution was right, also i had to add a return before the call to the axios function
return axios.get(url, options
)
.then(async function (response) {
if (response.status === 200){
group(response.data.arrayofdata).by('subapplication').reduce(function(id, entries) {
return {
appname: id,
mb: (entries.map(getBytes).reduce(add)) / 1048576
};
});
return sumatoria;

using async await in node js?

I am trying to implement async/await module. In function2 if user is not present i want to stop the execution there . i dont want to execute function 3, if user present , i want to execute function3
const function1() {
//code
return a
}
const function2= (a,email) => model.user.findOne({ email:email}).then((user) => {
if (!user) {
****// want to stop execution here****
} else {
//update details of user
}
return dealer;
});
const function 3 = function(dealer) {
//mail sending
};
exports.mailer = async(email,callback) => {
try {
var a =await function1();
var dealer =await function2(a,email); //stop execution here
var res = await function 3(dealer);
await callback(res);
}catch (err){
callback(err);
}
}
Returning a new Promise in function2 which resolves if a user is found, and rejects if not should achieve what you want I believe.
Something like this:
const function1 = () => {
return a
}
const function2 = (a, email) => {
return new Promise((resolve, reject) => {
model.user.findOne({
email: email
}).then((user) => {
if (!user) {
// want to stop execution here****
reject(new Error('Error Message'))
} else {
// update details of user
resolve(dealer)
}
})
})
}
const function3 = (dealer) => {
//mail sending
}
exports.mailer = async (email, callback) => {
try {
var a = await function1()
var dealer = await function2(a, email) // stop execution here
var res = await function3(dealer)
await callback(res)
} catch (err) {
callback(err)
}
}

Resources