im trying to get another api using node request, but when i try to display body.data its return undefined
router.get('/', (req, res,next) => {
request('http://localhost:3000/api/v1/promos', (error, response, body) => {
if(error) {
res.send('An erorr occured')
console.log(error)
}
else {
res.send(body.data)
}
});
});
anyone know whats wrong
If the body of your request is JSON, then you have to parse it to turn it into a Javascript object so you can access the .data property.
You can do that by passing the json: true option to request() and it will parse the JSON for you.
Or, you can manually parse the body with let result = JSON.parse(body).
Here's how you set the json: true option:
router.get('/', (req, res,next) => {
request({
url: 'http://localhost:3000/api/v1/promos',
json: true
}, (error, response, body) => {
if(error) {
res.send('An erorr occured')
console.log(error)
}
else {
res.send(body.data)
}
});
});
Related
I am playing around with the alpha vantage API and I am having trouble extracting the data in the else statement for viewing on the front end.
Here is my express route:
app.get('/', (req, res) => {
var url = 'https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=5min&apikey=apikey';
request.get({
url: url,
json: true,
headers: { 'User-Agent': 'request' }
}, (err, resp, data) => {
if (err) {
console.log('Error:', err);
} else if (resp.statusCode !== 200) {
console.log('Status:', resp.statusCode);
} else {
// data is successfully parsed as a JSON object:
// console.log(data);
}
})
res.render("index");
})
I want to pass the data variable in the else statement to res.render("index" {//get data into here});
I have tried assigning the data variable to another variable outside of request.get({}) but it does not seem to work. Any suggestions? :)
request.get is an asynchronous function, it means that everything inside the callback function below won't be executed immediately, it will wait until the request.get finish calling the endpoint and return the data then callback function will be executed.
// the callback function of `request.get`
(err, resp, data) => {
if (err) {
console.log('Error:', err);
} else if (resp.statusCode !== 200) {
console.log('Status:', resp.statusCode);
} else {
// data is successfully parsed as a JSON object:
// console.log(data);
}
})
In terms of execution flow, your res.render("index"); will be executed first before the callback function of request.get (it waits until the endpoint call finished), that's why you couldn't access data.
So, in order to res.render to access data, it should be put inside callback function so
(err, resp, data) => {
// ...other code
} else {
res.render('index', { data });
}
})
good reference to read about asynchronous https://www.freecodecamp.org/news/nodejs-eventloop-tutorial/
You can render it in the else statement.
app.get('/', (req, res) => {
var url = 'https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=5min&apikey=apikey';
request.get({
url: url,
json: true,
headers: { 'User-Agent': 'request' }
}, (err, resp, data) => {
if (err) {
console.log('Error:', err);
} else if (resp.statusCode !== 200) {
console.log('Status:', resp.statusCode);
} else {
res.render("index", {data}) // Change to something else
}
})
}}
I am using the Vimeo library to display a specific video.
My Node.js code:
app.get("/video/:id", (req, res) => {
client.request(
{
method: "GET",
path: `/videos/${req.params.id}`,
},
(error, body) => {
if (error) {
console.log(error);
}
res.send(body.data);
});
});
console.log() before res.send() displays the object perfectly but does not send it, even though I get 200 response, the body is completely empty.
I am using node js and making a call to spotify API and receive the response in body object, as shown in below code:
var options = {
url: 'https://api.spotify.com/v1/me',
headers: { 'Authorization': 'Bearer ' + access_token },
json: true
};
request.get(options, function(error, res, body) {
console.log(body)
});
This gives me output:
But now when I try to access the body object outside the function I get undefined. I think the problem is that I am making an asynchronous call and so before the response is received the statements where I make use of body variable outside function are executed. But I am a bit confused about how to get to the solution.
Any help is appreciated
Edit:
request.get(options, function(error, res, body) {
console.log(body)
response.render('user_account.html', {
data: body
})
});
And it gives the output:
Use promise.
You can try following:
const apiCall = () => {
return new Promise((resolve, reject) => {
var options = {
url: 'https://api.spotify.com/v1/me',
headers: { 'Authorization': 'Bearer ' + access_token },
json: true
};
request.get(options, function(error, res, body) {
if(error) reject(error);
console.log(body);
resolve(body);
});
});
}
apiCall().then((body) => {
// do your things here
})
.catch((err) => console.log(err));
i'm beginner at nodejs, i got a problem when request multiple url in a loop then i render it.
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:)
router.get('/', function(req, res, next) {
setInterval(function(){
request(url1,function (error,response,body) {
var data1 = JSON.parse(body);
request(url2+data1.access_token,function (error,response,body) {
var data_info = JSON.parse(body);
//error when it render
res.render('index', {data_info : data_info});
})
})
},5000);
});
That's not exactly a loop, I understand you mean that you call the same function repeteadly with setInterval().
Once you've sent your first response with res.render(), which finishes the response process for that request, subsequent attempts to use that res object fail.
If you want to send data to the client in 5 seconds interval you should probably either look into websockets or pass the setInterval() calls to the client so it polls your server each 5 seconds, in which case your server code could be changed to:
router.get('/', (req, res) => {
request(url1, (error, response, body) => {
const data1 = JSON.parse(body);
request(`${url2}${data1.access_token}`, (error, response, body) => {
const data_info = JSON.parse(body);
res.render('index', { data_info });
});
});
});
You can make use of Async Module
const async = require('async');
router.get('/', function (req, res, next) {
async.waterfall([
function(callback) {
request(url1, function (error,response,body) {
if(err) {
callback(err)
}else {
var data1 = JSON.parse(body);
callback(data1)
}
})
},
function(data1, callback) {
request(url2+data1.access_token, function(error,response,body) {
if(err) {
callback(err)
}else {
var data_info = JSON.parse(body);
callback(null, data_info)
}
})
}
], function(err, result) {
if(err) {
res.json({success: false, error: err, message: "Something went wrong.!"})
}else {
res.render('index', {
data_info : result
});
}
})
})
I want to make a backend call to an external api's and populate my page with the results. What is the best way to do this?
The "request.get" call is asynchronous, so I understand the code below is erroneous. However, I have written it in that fashion so that I can explain what I want to actually do.
Further, I may have 5-6 external api, is there a way to make this asynchronous for every api but synchronous get call?
This is how my current code looks like:
var express = require('express');
var request = require('request');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
var body = getRawApiResponse("someURL");
console.log("Index >" + body);
res.render('index', { title: 'Express', api: "some", body: body});
});
function getRawApiResponse(api){
request.get({
uri: api,
},
function(error, response, body){
if (!error && response.statusCode === 200) {
console.log("Index > Raw Api Response: " + body);
} else {
console.log(error);
}
});
}
You can wrap getRawApiResponse() in a promise
function getRawApiResponse(api){
return new Promise(function(resolve, reject){
request.get({
uri: api,
},
function(error, response, body){
if (!error && response.statusCode === 200) {
resolve(body)
} else {
reject(error)
}
});
});
}
which resolves on success and rejects in case of an error then you can chain it inside the get request like
router.get('/', function(req, res, next) {
getRawApiResponse("someURL")
.then(function(body){
res.render('index', { title: 'Express', api: "some", body: body});
})
.catch(err){
// do something
}
});
Look into Promises or async/await. You can use them to call your async apis and wait for the response making the call synchronous.
http://bluebirdjs.com/docs/getting-started.html
A Sample code of async/ await which u can modify for ur purpose is as below:
try{
let orderDetails = await MongoHelper.findOneByCriteria(MongoCollections.ORDER,searchCriteria);
}catch(err){
return err;
}
MongoHelper.findOneByCriteria = (collectionName, criteria) => {
return new Promise((resolve, reject) => {
db.collection(collectionName).find(criteria).toArray()
.then((results) => {
if (results.length > 0) {
resolve(results[0]);
} else {
resolve(null);
}
});
});
}
The best way is to use Promises to avoid callbacks hell. If you can use node.js v7.6 or higher, it could be much easier with async/await.
router.get('/', function(req, res, next) {
getRawApiResponse("someURL")
.then(body => {
console.log("Index >" + body);
res.render('index', { title: 'Express', api: "some", body: body});
});
});
function getRawApiResponse(uri) {
return new Promise((resolve, reject) => {
request.get({ uri }, (error, response, body) => {
if (err) {
reject(err);
}
resolve(body);
});
});
}
In the example about I use promisification to return a promise from getRawApiResponse, but there is already a module which do the same https://github.com/request/request-promise.