I cannot call an API inside for loop using nodejs - javascript

I'm trying to call an API inside a for loop using Nodejs,when the code is executed only the last element is called by the API:
the code :
var array=[12,124,852,256,5677,256,5679,2546,567,28,574]
for(var i=0;i<array.length;i=i++){
var b = array.splice(i,3);
const parameters1 = {
Ids: b.toString(),
limit: 45,
}
const get_request_args1 = querystring.stringify(parameters1);
const options1 = {
method: 'GET',
host: "host",
port: '443',
path: path + '?' + get_request_args1,
headers: {
'Accept': 'application/json',
'authorization': `Bearer ${token}`,
'Accept-Encoding': 'identity',
}
}
var req = http.request(options1, (res) => {
context.log("API CALL...",i);
var body = "";
var pages = 0;
var offset = [];
var limit = 100000;
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
const obj = JSON.parse(body);
//context.log('total pages 3 :', pages);
context.log('total :', obj.total);
context.res = { body: offset };
context.done();
});
}).on("error", (error) => {
context.log('ERROR :', error);
context.res = {
status: 500,
body: error
};
context.done();
});
}
when this code is executed only the last element in the array executed by the API, what I'm looking for is executing the api for each iteration of the for loop, any helps please ?

Not sure how your full function looks like, but you should build your function as fully structured as async-await.
And also you could use map function instead of for.
const yourFunction = async () => {
try {
const array = [12,124,852,256,5677,256,5679,2546,567,28,574];
const requests = array.map(async (item) => {
...
var req = await http.request(async options1, (res) => {
context.log("API CALL...",i);
...
});
await Promise.all(requests);
...
} catch (err) {
console.error(err);
}
}

Related

Return a response's body when using the await/async operators

I'm trying to convert a function that returns a Promise, to one that that uses await/async (which returns an implicit Promise, I understand).
This function "wraps" a call to the https.request object, the key part being the resolve(body) that returns the response's body:
promise_it = (data) => {
// throws FATAL
if (!data) {throw new Error('data is missing');}
return new Promise((resolve, reject) => {
let postData = JSON.stringify(data);
let options = {
hostname: 'httpbin.org',
port: 443,
path: '/post',
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// Accept: 'application/json'
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
const https = require('https');
let req = https.request(options, (res) => {
let body = [];
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
try {
body = JSON.parse(Buffer.concat(body).toString());
}
catch(e) {
console.error(e.message)
reject(e);
}
resolve(body);
});
});
req.on('error', (e) => {
console.error(e);
reject(e)
});
req.write(postData);
req.end();
});
}
try {
data = {firstName: 'Donald', lastName: 'Duck'}
const who = promise_it(data)
who
.then(r => console.info('INFO:',r))
.catch(e => console.error('ERROR:',e));
}
catch (error) {
console.error('FATAL:',error)
}
The function works as expected.
I translated this into an async/await function:
async_it = async (data) => {
if (!data) {throw new Error('data is missing');}
let postData = JSON.stringify(data);
let options = {
hostname: 'httpbin.org',
port: 443,
path: '/post',
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// Accept: 'application/json'
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
const https = require('https');
let req = https.request(options, (res) => {
let body = [];
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
try {
body = JSON.parse(Buffer.concat(body).toString());
// how do i return the body?
}
catch(e) {
console.error('HERE:',e.message)
throw e;
}
});
});
req.on('error', (e) => {
console.error('THERE:',e.message)
});
req.write(postData);
req.end();
}
(async () => {
try {
data = {firstName: 'Donald', lastName: 'Duck'}
const who = await async_it(data)
console.info('INFO:',who)
}
catch (error) {
console.error('FATAL:',error)
}
})();
But I can't seem to find a way to return the body. What am I missing?
Unfortunately https.request uses the "last parameter callback" Node.js style, so there is no possibility to use it as-is with async/await.
You could make a wrapper like in nodejs - How to promisify http.request? reject got called two times for example, and then you can use it like:
try {
const body = await httpsRequest(options, postData);
return body;
} catch (e) {
console.error('THERE:',e.message);
}
But the mentioned wrapper is not much less than your current one (Promise version).

Promise.all() with dynamically sized array of requests using await

I'm new to JavaScript and Promises. I need to send an array of requests using Promise.all and await. Unfortunately, I do not know the size of the array, so it needs to be dynamic. The array would be requests. Ex:
let arrayOfApiCreateRecords = [];
arrayOfApiCreateRecords.push(apiCreateRecords(req, { clientHeaders: headers, record }));
let responses = await Promise.all( arrayOfApiCreateRecords );
I tried to write my code like this, but I seem to be stuck. Is it possible to rewrite the code using Promise.all and await with a dynamic array of requests? Please advise. Below is what I have:
'use strict';
const { apiCreateRecords } = require('../../../records/createRecords');
const createRecords = async (req, headers) => {
let body = [];
let status;
for(let i = 0; i < req.body.length; i++) {
let r = req.body[i];
let record = {
recordId: r.record_Id,
recordStatus: r.record_status,
};
const response = await apiCreateRecords(req, { clientHeaders: headers, record });
status = (status != undefined || status >= 300) ? status : response.status;
body.push(response.body);
};
return { status, body };
};
module.exports = {
createRecords,
};
Okay, I'm going to use fetch API to demonstrate the usage of Promise.all()
Normal usage (for one fetch call)
let user = { username: 'john.doe', password: 'secret' };
try{
let res = await fetch('https://example.com/user/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
})
console.log('User creation response: ', res);
}
catch(err){
console.error('User creation error: ', err);
}
Now let's use Promise.all()
const users = [
{ username: 'john.doe', password: 'secret' },
{ username: 'jane.doe', password: 'i-love-my-secret' }
];
const requests = [];
// push first request into array
requests.push(
fetch('https://example.com/user/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user[0])
})
);
// push second request into array
requests.push(
fetch('https://example.com/user/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user[1])
})
);
try{
const responses = await Promise.all(requests);
console.log('User creation responses: ', responses);
}
catch(err){
console.log('User creation error: ', err);
}

Async/Await Method Issue

I am working on MERN Stack Application(Mean,Express,ReactJS,NodeJS). I have one issue is that I have many more methods in mlcontroller.js page and I call some methods on REST API so I call that methods under that API from mlrouter.js but all that API is Async so currently API takes data slots vise means I give u an example that in one time take 100 data from first method and then pass to another method and pass from all methods again come to first method and take next 100 data and repeat same process again but I need to take all data in one time means untill one method will not complete not move on another method how's that possible with node js?
I place my code here :
mlrouter.js
ensureApiAuthenticated,
authController.checkReadOnlyUser,
mlController.getAPIData,
mlController.getData,
mlController.getCRCDetails,
mlController.getDetails,
mlController.uploadData
)
MlController.js
async function getAPIData(req, res, next) {
try {
let loanboardapi = " ", dealersocket = " ";
loanboardapi = {
url: "https://loanboard.houstondirectauto.com/api/User/GetAuthorizationToken?username=amin#houstondirectauto.com&password=test#123",
method: "GET"
};
dealersocket = {
url: 'https://idms.dealersocket.com/api/authenticate/GetUserAuthorizationToken?username=ankur#houstondirectauto.com&password=H5d465#!ddfdd45dsfd688&InstitutionID=105815',
method: 'GET'
};
request(loanboardapi,
(err, res, body) => {
console.log("res = ", res);
console.log("body =", body);
loantoken = JSON.parse(body).token;
console.log(loantoken);
});
request(dealersocket,
(err, res, body) => {
console.log("res = ", res);
console.log("body =", body);
dealertoken = JSON.parse(body).Token;
console.log(dealertoken);
next();
});
}
catch (e) {
req.error = e;
next();
}
}
function getData(req, res, next) {
try {
let result;
request.get('https://idms.dealersocket.com/api/account/getaccountlist?token=' + dealertoken + '&LayoutID=2002313&PageNumber=1&accounttype=i&accountstatus=a,c,b,o,r,s,x',
(err, res, body) => {
console.log("res = ", res);
console.log("body =", body);
result = JSON.parse(body);
console.log(result);
totalpage = parseInt(result.TotalPages);
let resultdata = Object.assign({}, result.Data);
console.log(resultdata);
//getSSN(totalpage, dealertoken, next);
next();
})
}
catch (e) {
req.error = e;
next();
}
}
async function getCRCDetails(req,res,next) {
async.eachSeries(ssn, async (item) => {
let CBCOptions = {
method: "POST",
url: "https://loanboard.houstondirectauto.com/api/Report",
headers: {
"Content-Type": "application/json",
Cookie: "ci_session=udmojmlc5tfl3epbrmtvgu6nao2f031p",
},
body: JSON.stringify({
token: loantoken,
action: "CBCReport",
variables: {
ssn: item,
},
}),
};
let EMpInfoption = {
method: "POST",
url: "https://loanboard.houstondirectauto.com/api/Report",
headers: {
"Content-Type": "application/json",
Cookie: "ci_session=udmojmlc5tfl3epbrmtvgu6nao2f031p",
},
body: JSON.stringify({
token: loantoken,
action: "getEmployerInfo",
variables: {
ssn: item,
},
}),
};
try {
let resultCBCOptions = await requestpromise(CBCOptions);
let EmployerInfoOptions = await requestpromise(EMpInfoption);
console.log(resultCBCOptions)
console.log(EmployerInfoOptions)
CRCOptions.push(resultCBCOptions);
EmpOption.push(EmployerInfoOptions);
} catch (error) {
console.log(error);
}
},
() => {
next();
}
);
}
async function getDetails(req,res,next) {
for(let i =0;i<CRCOptions.length;i++){
for(let j=0;j<EmpOption.length;j++){
let resdata = JSON.parse(CRCOptions[i]);
console.log(resdata);
result = resdata.data.DigifiResponse;
console.log(result);
let bodydata = JSON.parse(EmpOption[i]).data;
let crcssn = JSON.parse(CRCOptions[i]).ssn;
let empssn = JSON.parse(EmpOption[i]).ssn;
console.log("CRCSSN=",crcssn);
console.log("EMPSSN=",empssn);
if(crcssn == empssn)
{
for(let r=0;r<result.length;r++){
let crcdata = result[r];
console.log(crcdata);
for(let b=0;b<bodydata.length;b++) {
let annual_income;
console.log(bodydata[b]);
let mergedata = Object.assign(crcdata, bodydata[b]);
console.log("merge", mergedata);
if (mergedata["IncomeFrequency"] == "Monthly") {
annual_income = (parseInt(mergedata["Income"]) * 12).toString();
console.log(annual_income);
}
else {
annual_income = mergedata["Income"];
}
let binary = {
"accounts_opened": mergedata["total_number_of_open_accounts"],
"bankruptcies": mergedata["total_number_of_bankruptcies"],
"collections": mergedata["total_number_of_collections"],
"credit_inquiries_last_6_months": mergedata["total_number_of_inquires_in_the_last_6_months"],
"past_due_accounts": mergedata["total_number_of_accounts_currently_past_due"],
"open_accounts": mergedata["total_number_of_open_accounts"],
"high_credit_limit": mergedata["total_credit_limit_amount"],
"annual_income": annual_income
}
console.log(binary);
let arraybinary = Object.assign({},binary);
console.log(arraybinary);
binarydata.push(arraybinary);
console.log(binarydata);
let categorical = {
"bankruptcies_last_18_months": mergedata["count_of_bankruptcies_last_24_months"],
"credit_inquiries_last_6_months": mergedata["count_of_auto_loan_inquiries_last_9_months"],
"months_since_most_recent_inquiry": mergedata["total_number_of_inquires_in_the_last_6_months"],
"ninety_plus_delinquencies_last_18_months": mergedata["total_number_of_accounts_with_90180_day_delinquencies"],
"number_of_accounts_currently_30dpd": mergedata["total_number_of_accounts_with_3059_day_delinquencies"],
"open_credit_accounts": mergedata["total_number_of_open_auto_accounts"],
"pre_loan_debt_to_income": mergedata["total_amount_of_credit_debt"],
"total_current_balance": mergedata["total_account_balance"],
"total_high_credit_limit": mergedata["total_credit_limit_amount"],
"annual_income": annual_income
}
console.log(categorical);
let arraycategory = Object.assign({},categorical);
console.log(arraycategory);
categoricaldata.push(arraycategory);
let Linear = {
"bankruptcies_last_18_months": mergedata["count_of_bankruptcies_last_24_months"],
"credit_inquiries_last_6_months": mergedata["count_of_auto_loan_inquiries_last_9_months"],
"months_since_most_recent_inquiry": mergedata["total_number_of_inquires_in_the_last_6_months"],
"ninety_plus_delinquencies_last_18_months": mergedata["total_number_of_accounts_with_90180_day_delinquencies"],
"number_of_accounts_currently_30dpd": mergedata["total_number_of_accounts_with_3059_day_delinquencies"],
"open_credit_accounts": mergedata["total_number_of_open_auto_accounts"],
"pre_loan_debt_to_income": mergedata["total_amount_of_credit_debt"],
"total_current_balance": mergedata["total_account_balance"],
"total_high_credit_limit": mergedata["total_credit_limit_amount"],
"annual_income": annual_income
}
console.log(Linear);
let arraylinear = Object.assign({},Linear);
console.log(arraylinear);
Lineardata.push(arraylinear);
}
}
}
break;
}
}
console.log(binarydata.length);
console.log(binarydata);
converter.json2csv(binarydata,(err,csv) => {
if(err)throw err;
console.log(csv);
file.writeFileSync('/home/rita_gatistavam/Downloads/CSV/binarydata.csv',csv);
console.log('File Written');
})
converter.json2csv(Lineardata,(err,csv) => {
if(err)throw err;
console.log(csv);
file.writeFileSync('/home/rita_gatistavam/Downloads/CSV/lineardata.csv',csv);
console.log('File Written');
})
converter.json2csv(categoricaldata,(err,csv) => {
if(err)throw err;
console.log(csv);
file.writeFileSync('/home/rita_gatistavam/Downloads/CSV/categorydata.csv',csv);
console.log('File Written');
})
next();
}
async function uploadData(req,res,next){
let moduletype = sessionStorage.getItem('moduletype');
console.log(moduletype);
req.params.id = sessionStorage.getItem('modelid');
console.log(req.params.id);
try {
res.status(200).send({
status: 200,
timeout: 10000,
type: 'success',
text: 'Changes saved successfully!',
successProps: {
successCallback: 'func:window.createNotification',
},
responseCallback: 'func:this.props.reduxRouter.push',
pathname: `/ml/models/${req.params.id}/training/historical_data_${moduletype}`,
});
} catch (e) {
periodic.logger.warn(e.message);
res.status(500).send({ message: 'Error updating model type.', });
}
}```
Cannot understand your question, but I assume you want to get all the async request in one go.
You can achieve this with Promise.all, all the results will be returned as an array, and all the request will run at the same time.
const results = await Promise.all([asyncRequest1, asyncRequest2, asyncRequest3])
getting resulsts sequentially.
await asyncRequest1();
await asyncRequest2();
await asyncRequest3();

How to get a variable out of http request NodeJS?

I would like to use two IBM Watson services and combine the responses from both in one variable and return it as a callback. I couldn't figure out how to get response1 value outside the http request to combine it with response2 from the other IBM Watson service.
I tried the below code and it didn't work. I read that I can use promises, but I'm pretty new to this, and couldn't figure out how to do this.
Can anyone help please?
const AWS = require('aws-sdk');
var http = require('https');
exports.handler = (event, context, callback) => {
var text = JSON.stringify(event.text);
var options = {
method: process.env.method,
hostname: process.env.watson_hostname,
port: null,
path: process.env.path,
headers: {
'content-type': process.env.content_type,
authorization: process.env.authorization,
'cache-control': process.env.cache_control,
'X-Watson-Learning-Opt-Out': 'true'
}
};
var req = http.request(options, function (res) {
var chunks = "";
res.on("data", function (chunk) {
chunks+ = chunk.toString();;
});
res.on("end", function () {
var response1 = (chunks);
//////////////here I need to get reponse2
var response2 = IBM2();
var bothResponses = response1 + response2
callback(null,bothResponses)
});
})
req.write(text);
req.end()
function IBM2(){
var text = JSON.stringify(event.text);
var options = {
method: process.env.method2,
hostname: process.env.watson_hostname2,
port: null,
path: process.env.path2,
headers: {
'content-type': process.env.content_type2,
authorization: process.env.authorization2,
'cache-control': process.env.cache_control,
'X-Watson-Learning-Opt-Out': 'true'
}
};
var req = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var response2 = JSON.parse(Buffer.concat(chunks));
return(response2)
}
Return a promise from your IBM2 function and handle using async await in the calling function. Notice the async keyword before on end callback.
I have tried to add Promise to your existing flow:
const AWS = require('aws-sdk');
var http = require('https');
exports.handler = (event, context, callback) => {
var text = JSON.stringify(event.text);
var options = {
method: process.env.method,
hostname: process.env.watson_hostname,
port: null,
path: process.env.path,
headers: {
'content-type': process.env.content_type,
authorization: process.env.authorization,
'cache-control': process.env.cache_control,
'X-Watson-Learning-Opt-Out': 'true'
}
};
var req = http.request(options, function (res) {
var chunks = "";
res.on("data", function (chunk) {
chunks += chunk.toString();;
});
res.on("end", async function () {
var response1 = (chunks);
//////////////here I need to get reponse2
var response2 = await IBM2();
// validate response2 (in case IBM2 throws error)
var bothResponses = response1 + response2;
callback(null,bothResponses)
});
});
req.write(text);
req.end();
function IBM2(){
return new Promise((resolve, reject) =>{
var text = JSON.stringify(event.text);
var options = {
method: process.env.method2,
hostname: process.env.watson_hostname2,
port: null,
path: process.env.path2,
headers: {
'content-type': process.env.content_type2,
authorization: process.env.authorization2,
'cache-control': process.env.cache_control,
'X-Watson-Learning-Opt-Out': 'true'
}
};
var req = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var response2 = JSON.parse(Buffer.concat(chunks));
resolve(response2)
});
res.on("error", function (err) {
reject(err);
});
})
});
}
};
Before making any changes to your code, I would suggest you go thru these topics first.
For reference, do take a look into the concept of promises and async-await
Promiese
Async/Await
Dont know if you have other errors, but it looks like youre not waiting for response2 to finish, maybe something like
const response2 = await IBM2():
or if you want to use promises maybe something like:
res.on('end', function () {
var response2 = IBM2().then(
val => {
var bothResponses = response1 + val;
callback(null, bothResponses);
},
reject => {
/* handle rejection here */
},
);
});

res.json is not a function - nodejs

I've got this error using res.json to get the return of my function and this is code is been used em anothers places as wrote below, running fine.
async function getPlaylist(req, res, playlistId) {
try {
// const calltoken = await getToken()
// const token = calltoken.data.access_token
// console.log(token)
const config = {
headers: {
'Authorization': 'Bearer ' + 'BQA0K9bKgBVn8xTp-yTsoaKs5VfS7EyjMIL03OEOy05wq08ZmLkNfqbbnsL_hFT1AV2FGN5tAQdeDV1X224', //token,
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}
const url = 'https://api.spotify.com/v1/playlists/1j2L3DjzZ3SdN64r83Sblj?si=cuvOrPONSO6caE9XD6smEg'
await axios.get(url, config)
.then(function (response) {
var playlist = response
var items = playlist.data.tracks.items
// console.log(items)
const playlistfull = []
items.forEach(index => {
var playlistdata = {
name: index.track.name,
artists: index.track.album.artists[0].name,
album: index.track.album.name,
url: index.track.external_urls.spotify
}
playlistfull.push(playlistdata)
})
return res.json(playlistfull)
})
} catch (error) {
return console.log(error)
}
}
You have to use in NodeJS
Node's res give parameter to function
const router = express.Router();
router
.route('/')
.get((req, res) => {
const playlistId = 'asdf';
getPlaylist(req, res, playlistId);
return;
});

Categories

Resources