Consuming data of restAPI using Node - javascript

I am calling below restAPI using node JS.
I am using below code.
var Request = require("request");
Request.get("http://localhost:8080/ords/hr/rest-v3/item/Sugar", (error, response, body) => {
if (error) {
return console.dir(error);
}
console.log(response.body);
});
It is giving below output which is correct.
{"items":[{"itemid":101,"itemname":"Sugar","itemcost":32.5}],"hasMore":false,"limit":0,"offset":0,"count":1,"links":[{"rel":"self","href":"http://localhost:8080/ords/hr/rest-v3/item/Sugar"},{"rel":"describedby","href":"http://localhost:8080/ords/hr/metadata-catalog/rest-v3/item/item"}]}
How can I access only itemcost, not entire body. I am new to node so not familiar with many things.
Can you please help me on that.

May be it can help you.
var Request = require("request");
Request.get("http://localhost:8080/ords/hr/rest-v3/item/Sugar", (error, response, body) => {
if (error) {
return console.dir(error);
}
let jsonData = JSON.parse(response.body);
let obj= new Object(jsonData);
obj.items.forEach(itemChild => {
let cost=itemChild.itemcost;
console.log(cost);
})
});

you can iterate the response.body.items and get the costs of all items in the items array like this,
var Request = require("request");
Request.get("http://localhost:8080/ords/hr/rest-v3/item/Sugar", (error, response, body) => {
if (error) {
return console.dir(error);
}
console.log(response.body);
const itemCosts = response.body.items.map(item => item.itemcost);
console.log(itemCosts);
});

Considering your input you can simply do this:
let input = {
"items": [
{
"itemid": 101,
"itemname": "Sugar",
"itemcost": 32.5
}
],
"hasMore": false,
"limit": 0,
"offset": 0,
"count": 1,
"links": [
{
"rel": "self",
"href": "http://localhost:8080/ords/hr/rest-v3/item/Sugar"
},
{
"rel": "describedby",
"href": "http://localhost:8080/ords/hr/metadata-catalog/rest-v3/item/item"
}
]
};
let json = JSON.parse(JSON.stringify(input));
json.items.map(item =>{
console.log(item.itemcost)
})
You can find running solution here

Related

node for loop keep looping

I use request to read a website then parseString to convert and later save as json. The problem is saving. Looks like "for loop" keeps looping and when is saving the information uses the last info from var cta to assign to information. I have try asyn await but it didnt work. thanks in advance.
var fs = require('fs');
var request = require('request');
var parseString = require('xml2js').parseString;
var json = {} ;
var cta = [
{
"_id": 1,
"name": "PRWeb",
"feedtype": "Misc",
"feedaddress": "https://www.prweb.com/rss2/daily.xml",
"status": true
},
{
"_id": 2,
"name": "Business Wire",
"feedtype": "Industrie",
"feedaddress": "https://feed.businesswire.com/rss/home/?rss=G1QFDERJXkJeGVtRVQ==",
"status": false
},
{
"_id": 3,
"name": "News Wire",
"feedtype": "Daily News",
"feedaddress": "https://www.newswire.com/newsroom/rss/custom/all-press-releases",
"status": true
}
];
for (var i = 0; i < cta.length; i++) {
function getDatos(url, callback) {
request(url, function(error, response, data){
callback(error, response, data);
});
}
if (cta[i].status === true) {
console.log("cta: " + cta[i].feedaddress);
agrabar = cta[i];
console.log("agrabar: " + agrabar.feedaddress);
getDatos(agrabar.feedaddress, function(error, response, data){
parseString(data, {explicitArray: false}, function (err, result) {
if (err) {
return console.log('unable to parse XML');
}
json = {rssfeeder: agrabar, feed: result.rss.channel.item};
console.log(json);
fs.appendFile ("output.json", JSON.stringify(json, null, 4), function(err) {
if (err) throw err;
console.log('complete');
});
});
});
}
}
console.log('DONE!!!')
You seem to be mixing asynchronous code with synchronous code. It'd be great if you read more about how (and in what order) callbacks are handled in Javascript.
Example : Your final line of code console.log('DONE!!!') should actually be printed at the last when everything has finished, but when you'll run it, you'll be surprised that it's actually the first line to be printed to console. This is because the function getDatos is an asynchronous function, meaning that it will execute at some later point in time. Your for loop executes synchronously meaning that getDatos will be called thrice in the correct order, but owing to function closure in JS and asynchronicity, getDatos will be called after your final console.log has been done.
Furthermore, it's a good practice to use async await and Promises in modern JS, since it makes reading the code much more easier. I have modified your code to do what you intend to do and here it is. Hope it helps!
var fs = require('fs');
var request = require('request');
var parseString = require('xml2js').parseString;
var cta = [
{
"_id": 1,
"name": "PRWeb",
"feedtype": "Misc",
"feedaddress": "https://www.prweb.com/rss2/daily.xml",
"status": true
},
{
"_id": 2,
"name": "Business Wire",
"feedtype": "Industrie",
"feedaddress": "https://feed.businesswire.com/rss/home/?rss=G1QFDERJXkJeGVtRVQ==",
"status": false
},
{
"_id": 3,
"name": "News Wire",
"feedtype": "Daily News",
"feedaddress": "https://www.newswire.com/newsroom/rss/custom/all-press-releases",
"status": true
}
];
function getDatos(cta_object) {
if (cta_object.status === false){
return new Promise((resolve, reject) => resolve(false));
}
else {
return new Promise((resolve, reject) => {
request(cta_object.feedaddress, (err, response, data) => {
if (err) reject(err);
else resolve(data);
})
})
.then((data) => {
return new Promise((resolve, reject) => {
parseString(data, {explicitArray: false}, (err, result) => {
if (err) {
console.error("Unable to parse XML!");
return reject(err);
}
else return resolve(result);
});
})
})
.then((result) => {
console.log(result);
return {
'rssfeeder': cta_object,
'feed': result.rss.channel.item
};
})
.then((json) => {
return new Promise((resolve, reject) => {
fs.appendFile ("output.json", JSON.stringify(json, null, 4), function(err) {
if (err) reject(err) ;
console.log("complete!");
resolve(true);
});
})
})
.catch((err) => {
throw(err);
})
}
};
Promise.all(cta.map((cta_obj) => getDatos(cta_obj)))
.then(() => console.log('DONE!!!'))
.catch((err) => {
throw err;
})

How to do a POST request from within Hubot?

I'm trying to code a Hubot listener that would automatically create a JIRA issue from a specific chat dialogue. Here's the example (I used Hubot-Rocketchat boilerplate code from here: https://github.com/RocketChat/hubot-rocketchat-boilerplate)
module.exports = (robot) => {
robot.hear(/^#alerts (.*)/i, (res) => {
const jiraurl="https://jira.example.com/rest/api/2/issue/"
const jiraproject="ALERTS"
text = res.match[1]
data = JSON.stringify({
"fields": {
"project":
{
"key": `#{jiraproject}`
},
"summary": `#{text}`,
"description": "Задача создана автоматически из RocketChat",
"issuetype": {
"name": "Инцидент"
}
}
})
/* res.reply(data) */
res.reply(`Создаю задачу в JIRA: ${text}`)
robot.http(jiraurl)
.header('Content-Type', 'application/json')
.post(data) (err, response, body) =>
if err
res.send `Ошибка: #{err}`
return
})
}
What would be the proper way to do this?

how to get key value pair from body object in javascript while using request module

I am creating an application in which I want to use some data from a JSON, which is generated by another js file. Here is the code which is generating JSON
var request = require('request');
module.exports = {
foo:
request('https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/c1d1e5d6-fe5c-42de-8713-60f272a3b63e?subscription-key=d3d3e4dfa8744be9b4ae47558df8fc5a&timezoneOffset=0&verbose=true&q=hey',function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log(body);
})
};
I am interested in body object, which is giving following contents -
{
"query": "hey",
"topScoringIntent": {
"intent": "Help",
"score": 0.500165462
},
"intents": [
{
"intent": "Help",
"score": 0.500165462
},
{
"intent": "None",
"score": 0.10364107
},
{
"intent": "SearchHotels",
"score": 0.00249445555
},
{
"intent": "ShowHotelsReviews",
"score": 9.451727E-06
}
],
"entities": []
}
Now I want to access value of intent from topScoringIntent element. That to in another JS file. I tried using body[1].intend but it gives undefined.
I am very new to javascript and need very basic code to do this. Please give some suggestions on this. Also plz tell me if this can be solved by body-parser and if yes then how?
Update - Here is the code where I want to use body['topScoringIntent'].intent as global.
require('dotenv-extended').load();
var builder = require('botbuilder');
var restify = require('restify');
var Store = require('./store');
var spellService = require('./spell-service');
var request = require('request');
var myJSON = require("JSON");
var fs = require('fs');
//var window = window;
var request = require("request");
var myJSON = require("JSON");
var globalVar = [];
// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log('%s listening to %s', server.name, server.url);
});
// Create connector and listen for messages
var connector = new builder.ChatConnector({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
server.post('/api/messages', connector.listen());
function getMyBody(url, callback) {
request({
url: 'https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/c1d1e5d6-fe5c-42de-8713-60f272a3b63e?subscription-key=d3d3e4dfa8744be9b4ae47558df8fc5a&timezoneOffset=0&verbose=true&q=hey',
json: true
}, function (error, response, body) {
if (error || response.statusCode !== 200) {
return callback(error || {statusCode: response.statusCode});
}
global.topScoringIntent = body['topScoringIntent'].intent;
//if(body['topScoringIntent'].intent == 'Help');
//console.log('yay');
callback(null, body);
});
}
getMyBody('https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/c1d1e5d6-fe5c-42de-8713-60f272a3b63e?subscription-key=d3d3e4dfa8744be9b4ae47558df8fc5a&timezoneOffset=0&verbose=true&q=hey', function(err, body) {
if (err) {
console.log(err);
}
})
if(body['topScoringIntent'].intent == 'Help');
console.log('success');
This should work for you
console.log(response.topScoringIntent.intent);
body.topScoringIntent.intent will return 'Help'.
To use it globally you can set a var :
var body = {
"query": "hey",
"topScoringIntent": {
"intent": "Help",
"score": 0.500165462
},
"intents": [
{
"intent": "Help",
"score": 0.500165462
},
{
"intent": "None",
"score": 0.10364107
},
{
"intent": "SearchHotels",
"score": 0.00249445555
},
{
"intent": "ShowHotelsReviews",
"score": 9.451727E-06
}
],
"entities": []
}
var result = body.topScoringIntent.intent;
And then use result somewhere else :
console.log(result);

node js + express + jade iterate array

What I'm trying to do is iterate over an array in a jade layout. The layout file is lessons.jade:
each lesson in myLessons
ul.nav.pull-center: li.dropdown.nav.text-center
.btn.btn-default.dropdown-toggle.btn-lg.btn-block(data-toggle="dropdown" aria-expanded="false")= lesson.day
ul.dropdown-menu.col-xs-12
each lessonName in myLessons
li: a(href='/lessons/details')= lessonName.name
li.divider
My view controller file is lessons.js:
var renderLessonPage = function (req, res, responseBody) {
var message;
if (!(responseBody)) {
message = "Lessons API Error!";
} else {
if (responseBody.length < 0) {
message = "No lessons found!";
}
}
res.render('lessons', {
title: 'Lesson page',
pageHeader: {
title: 'Just a page'
},
myLessons: responseBody,
message: message
});
};
module.exports.lessons = function(req, res) {
var requestOptions, path;
path = '/api/locations/' + req.params.locationid + '/lessons/';
requestOptions = {
url: apiOptions.server + path,
method: "GET",
json: {}
};
request(
requestOptions,
function (err, response, body) {
renderLessonPage(req, res , body );
}
);
};
My API controller file contains:
var sendJsonResponse = function (res, status, content) {
res.status(status);
res.json(content);
};
module.exports.lessons = function (req, res) {
loc
.findById(req.params.locationid)
.populate('lessons')
.exec(function (err, location) {
if (!location) {
sendJsonResponse(res, 404, {
"message": "No lessons found!"
});
} else {
response = {
location: {
lessons: location.lessons
// id: req.params.locationid
}
};
sendJsonResponse(res, 200, response);
}
})
};
If I fire up Chrome and browse to the location accessed by the API, I see the following json result:
{
"location": {
"lessons": [
{
"_id": "56d5d947bdb5c3d92ace848c",
"name": "Henk",
"startTime": "13:00",
"endTime": "14:00",
"day": "Tuesday",
"__v": 0
},
{
"_id": "56d5d9dfea5cbcf42a20f87e",
"name": "skaaak",
"startTime": "12:00",
"endTime": "18:00",
"day": "Monday",
"__v": 0
}
]
}
}
If I enable console.log in my jade layout template via - console.log and catch the lesson in myLessons, the exact same thing is outputted in the console. But I just can't use values from the array in my jade layout.
I get one dropdown menu only instead of two, the text isn't populated on the dropdown button, and there are two empty items in the pull down menu.
I tried many things, but most resulted in undefined or properties which couldn't be read.
When you sent result for your request
response = {
location: {
lessons: location.lessons
// id: req.params.locationid
}
};
sendJsonResponse(res, 200, response);
response is object, not array. So when renderLessonPage function render (option myLessons: responseBody) is object.
You can replace your code as below:
response = {
location: {
lessons: location.lessons
// id: req.params.locationid
}
};
sendJsonResponse(res, 200, response.location.lessons);

Elastic search Parser Error

I'm trying to construct the following search call in Javascript with no luck, the below works fine so I know my index is setup correctly in ES.
GET /teachersx9/teacher/_search
{
"query": {
"bool": {
"must": [
{ "match_all": {}},
{
"nested": {
"path": "langs",
"score_mode": "max",
"query": {
"bool": {
"must": [
{ "match": { "languagename": "Afrikaans"}}
]
}}}}
]
}}}
However, when trying to create the query on my server using:
app.get('/search', function(req, res) {
var term = req.query.term;//req.param('term');
var urlPath = 'https:.../teachersx9/teacher/_search';
//var obj = {};
var query = {};
query.bool = {};
var match_all = {};
var nested = {path:"langs", score_mode:"max"};
nested.query = {};
nested.query.bool = {};
nested.query.bool.must = [{match: {languagename:term}}];
query.bool.must = [{match_all:match_all}, {nested:nested}];
console.log(query);
request.post({
url: urlPath,
json: true,
body: query
}, function(error, response, body){
if (!error && response.statusCode == 200) {
console.log(body);
res.send(body);
} else {
console.log(body);
res.send(response);
}
});
});
Error I get back from ES as part of the response:
"statusCode": 400,
"body": {
"error": "SearchPhaseExecutionException[Failed to execute phase [query_fetch], all shards failed; shardFailures {[FMwFQZmkIAfOE7X48Q][teachersx9][0]: RemoteTransportException[[Quentin Quire][inet[/172.31.7.165:9300]][indices:data/read/search[phase/query+fetch]]]; nested: SearchParseException[[teachersx9][0]: from[-1],size[-1]: Parse Failure [Failed to parse source [{\"bool\":{\"must\":[{\"match_all\":{}},{\"nested\":{\"path\":\"langs\",\"score_mode\":\"max\",\"query\":{\"bool\":{\"must\":[{\"match\":{\"languagename\":\"Italian\"}}]}}}}]}}]]]; nested: SearchParseException[[teachersx9][0]: from[-1],size[-1]: Parse Failure [No parser for element [bool]]]; }]",
"status": 400
},
bool isn't a valid top-level construct in the Elastic query DSL. You need to wrap it in query.
var body = { query: query }
request.post({
url: urlPath,
json: true,
body: body
})

Categories

Resources