I'm trying to retrieve the response(var body) from response_handler function to my /image/search route. But the problem is I cannot do it by making it (var body) a global variable since it's asynchronous.
router.get('/imagesearch/:term', (req, res) => {
let term = req.params.term;
bing_web_search(term);
res.json('trying to add json response here')
});
let host = 'api.cognitive.microsoft.com';
let path = '/bing/v7.0/search';
let response_handler = function (response) {
let body = '';
response.on('data', function (d) {
body += d;
});
response.on('end', function () {
console.log('\nRelevant Headers:\n');
for (var header in response.headers)
// header keys are lower-cased by Node.js
if (header.startsWith("bingapis-") || header.startsWith("x-msedge-"))
console.log(header + ": " + response.headers[header]);
body = JSON.stringify(JSON.parse(body), null, ' ');
console.log('\nJSON Response:\n');
console.log(body);
});
response.on('error', function (e) {
console.log('Error: ' + e.message);
});
};
let bing_web_search = function (search) {
console.log('Searching the Web for: ' + search);
let request_params = {
method : 'GET',
hostname : host,
path : path + '?q=' + encodeURIComponent(search),
headers : {
'Ocp-Apim-Subscription-Key' : subscriptionKey,
}
};
let req = https.request(request_params, response_handler);
req.end();
}
Related
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);
}
}
I am calling API to fetch data on the basis of that data I am calling different APIs which is based on condition.
I have used a promise to maintain the async code as well but no luck so far. At the end of the block, I want every data pushed inside array but I am getting a blank array.
async (body, nextCall) => {
var tmpArryOfModuleList = []
var bodyData = body.data
var promise = new Promise((resolve, reject) => {
bodyData.forEach(element => {
if (element.hasCRUD === '0') {
var options = {
method: 'GET',
url: `${apiURL}/api/fetchAllCharts`,
headers:
{
Authorization: token
}
};
request(options, function (error, response, dashboardData) {
if (error) {
return nextCall({
error: error
})
}
var parsedDashboardData = JSON.parse(dashboardData)
for (var i = 0; i < parsedDashboardData['data'].length; i++) {
var val = element.name + " - " + parsedDashboardData['data'][i]['name']
var randomID = Math.random().toString(36).slice(2)
tmpArryOfModuleList.push({ "_id": randomID, "submodule": val })
}
});
} else if (element.hasCRUD == '1') {
var options = {
method: 'GET',
url: `${apiURL}/api/fetchAllActions`,
headers:
{
Authorization: token
}
};
request(options, function (error, response, crudData) {
if (error) {
return nextCall({
error: error
})
}
var parsedcrudData = JSON.parse(crudData)
for (var i = 0; i < parsedcrudData['data'].length; i++) {
var val = element.name + " - " + parsedcrudData['data'][i]['name']
var randomID = Math.random().toString(36).slice(2)
tmpArryOfModuleList.push({ "_id": randomID, "submodule": val })
}
});
} else {
console.log('no data found')
reject('No Data Found')
}
})
resolve(tmpArryOfModuleList)
})
console.log('tmpArryOfModuleList', tmpArryOfModuleList)
}
What am I doing wrong? How can I achieve the result on the last array?
I have a NodeJS code using request module to make a request to the server. The code works fine if I use 'http.request' but shows error on res.on() while using request to make the call. Following is the part showing the error:
const Request = require("request");
.
.
.
function getRequiredTime(lc, lat, lon, id, response, callback) {
const start = new Date();
const ReqObj = {
host: 'localhost',
port: process.env.PORT,
path: '/something/' + lc + '/' + lat + '/' + lon +'/' + id,
method: 'GET'
};
const RespObj = {};
const requestBody = {};
requestBody.id = id;
requestBody.app_name = "someApp";
requestBody.hostname = ReqObj.hostname;
requestBody.path = ReqObj.path;
requestBody.msg = "Some message";
requestBody.body = "";
logger.info(JSON.stringify(requestBody));
const getReq = Request(ReqObj, function (res) {
if (res.statusCode === 400) {
response.send("Some message");
} else if (res.statusCode === 500) {
response.send("Some message");
} else if (res.statusCode === 501) {
response.send("Some message");
} else {
let duration = parseInt(15);
res.on('data', function (durationtime) {
const end = new Date();
const end = *****;
const responseDat = {
'id': id,
'start': start,
'end': end,
'time': end,
'service_name': 'someName'
};
duration += parseInt(durationtime);
const time = parseInt(duration);
RespObj.id = id;
RespObj.app_name = "getApp";
RespObj.msg = "Some message";
RespObj.body = time;
logger.info(JSON.stringify(RespObj));
callback(time);
});
res.on('error', function (error) {
logger.error(`ERROR`);
});
}
});
getReq.end();
};
.
.
.
This is the error I am getting when trying to hit the url with ARC or postman:
TypeError: res.on is not a function at Request._callback
at self.callback
at Request.emit
at Request.init
at new Request
res.on() is an event of http module, not request module. In your case, body contains your data and no need res.on event when change your callback function to
const getReq = Request(ReqObj, function (err, res, body) {
I am calling a javascript function , which in turn calls a web service;The response of this service is used to call another function which also calls a service. At end of both services we set session attributes. This code gives no errors, but the callback gets called before the service has returned data. The main motive of this code is to set the session attributes before return of flow from this code, when the callback gets called before the service has returned values the session attributes are not set and the requirement of the code is not fulfilled.
'use strict';
function close(sessionAttributes, fulfillmentState, message) {
return {
sessionAttributes,
dialogAction: {
type: 'Close',
fulfillmentState,
message : 'For security purpose answer these questions '
},
};
}
function getSecurityQuestions(intentRequest, context, post_options, callback){
const sessionAttributes = intentRequest.sessionAttributes || {};
var policynumber = sessionAttributes.policynumber;
var interactionID = sessionAttributes.interactionID;
var body = "";
var body2;
const http = require('https');
const promise = new Promise((resolve, reject) => {
const post_data = JSON.stringify({"Purpose":"SecurityQuestions", "InteractionID":interactionID, "SearchStringAcctNum":policynumber});
//ignores SSL
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var post_request = http.request(post_options, function(res) {
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
context.done(body);
resolve(body);
});
res.on('error', function(e) {
reject(Error(e.message));
context.fail('error:' + e.message);
});
});
// post the data
post_request.write(post_data);
post_request.end();
});
callback( promise.then((body) => {
body2 = JSON.parse(body);
sessionAttributes.question1 = body2.SecurityDetails[0].Question;
close(sessionAttributes, 'Fulfilled');
}, (error) => {
console.log(error.message);
})
);
}
function getInteraction(intentRequest, context, callback) {
const slots = intentRequest.currentIntent.slots;
var policynumber = "PA"+slots.PolicyNumber;
var questionOne = slots.questionOne;
var questionTwo = slots.questionTwo;
const sessionAttributes = intentRequest.sessionAttributes || {};
console.log("policy number : "+policynumber + "question 1 : "+questionOne + "question 2 : "+questionTwo);
sessionAttributes.policynumber = policynumber;
var body = "";
var body2;
// An object of options to indicate where to post to
var post_options = {
host: 'example.com',
protocol: 'https:',
port: '3000',
path: '/hiddenPath',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
const http = require('https');
const promise = new Promise((resolve, reject) => {
const post_data = JSON.stringify({"Purpose":"CreateInteraction"});
//ignores SSL
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var post_request = http.request(post_options, function(res) {
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
context.done(body);
resolve(body);
});
res.on('error', function(e) {
console.log("rejected here");
reject(Error(e.message));
context.fail('error:' + e.message);
});
});
// post the data
post_request.write(post_data);
post_request.end();
});
callback( promise.then((body) => {
body2 = JSON.parse(body);
console.log("interaction ID : "+body2.InteractionID);
sessionAttributes.interactionID = body2.InteractionID;
getSecurityQuestions(intentRequest, context, post_options, callback);
}, (error) => {
console.log('Promise rejected.');
console.log(error.message);
}));
}
// --------------- Intents -----------------------
/**
* Called when the user specifies an intent for this skill.
*/
function dispatch(intentRequest, context, callback) {
const intentName = intentRequest.currentIntent.name;
if (intentName === 'currIntent') {
return getInteraction(intentRequest, context, callback);
}
throw new Error(`Intent with name ${intentName} not supported`);
}
// --------------- Main handler -----------------------
function loggingCallback(response, originalCallback) {
console.log("logging callback called......");
originalCallback(null, response);
}
exports.handler = (event, context, callback) => {
try {
dispatch(event, context, (response) => loggingCallback(response, callback));
} catch (err) {
callback(err);
}
};
You should resolve your promise only after the request ends.. Have updated your sample below. Hope it helps. Also, you were sending an invalid object as your post body. Fixed that as well.
function getValue(context, post_options, callback) {
var body = "";
var body2;
const http = require('http');
const promise = new Promise((resolve, reject) => {
// INVALID OBJECT
//const post_data = JSON.stringify({"something"});
const post_data = JSON.stringify({
something: "something"
});
//ignores SSL
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var post_request = http.request(post_options, function(res) {
res.on('data', function(chunk) {
body += chunk;
console.log("inside " + JSON.stringify(body));
// DONT RESOLVE HERE, REQUEST IS NOT COMPLETE
//resolve(body);
});
res.on('end', function() {
context.done(body);
//RESOLVE HERE INSTEAD
resolve(body);
});
res.on('error', function(e) {
reject(Error(e.message));
context.fail('error:' + e.message);
});
});
// post the data
post_request.write(post_data);
post_request.end();
});
promise.then((body) => {
console.log("response data " + JSON.stringify(body));
body2 = JSON.parse(body);
callback(delegate(sessionAttributes, intentRequest.currentIntent.slots));
}, (error) => {
console.log('Promise rejected.');
console.log(error.message);
});
}
I wrote this function that fetches a file from a URL, taking redirects into account:
const fetchFile = (url, successCallback, errorCallback) => {
http.get(url).on('response', function(response) {
var body = ''
if((response.statusCode == 301) || (response.statusCode == 302)) {
console.log('Redirection for ' + url + ' to ' + response.headers.location + ' caught...')
fetchFile(response.headers.location, successCallback, errorCallback)
return
}
response.on('data', function(chunk) {
body += chunk
})
response.on('end', function() {
console.log('Completed!')
successCallback(body)
})
})
}
This code seems to work correctly, and now I am trying to rewrite it to use promises without any external modules, but I'm not making much headway. I came up with this code:
const fetchFileProm = function(url) {
console.log('In fetchFileProm()');
return new Promise((resolve, reject) => {
console.log('In Promise function body')
var req = http.get(url, (response) => {
console.log('In Response handler func body');
var body = ''
if((response.statusCode == 301) || (response.statusCode == 302)) {
console.log('Redirection for ' + url + ' to ' + response.headers.location + ' caught...')
return fetchFileProm(response.headers.location)
}
response.on('data', (fragment) => { body += fragment })
response.on('end', () => resolve(body) )
})
req.on('error', function(err) {
reject(err)
})
})
}
When I run this, I get the In Promise function body message but nothing further than that. What am I doing wrong here?
When you're in an asynchronous operation, a regular return doesn't work so when you're doing return fetchFileProm(response.headers.location), nothing takes care of that return and there's nothing that will ever resolve your promise.
What you need to do is to recursively pass the callbacks to the next asynchronous operation:
...
var req = http.get(url, (response) => {
console.log('In Response handler func body');
var body = ''
if((response.statusCode == 301) || (response.statusCode == 302)) {
console.log('Redirection for ' + url + ' to ' + response.headers.location + ' caught...')
fetchFileProm(response.headers.location).then(resolve, reject);
} else {
response.on('data', (fragment) => { body += fragment })
response.on('end', () => resolve(body) )
}
})
...