variable is not defined inside http request in node and express - javascript

In my express action get('items') I'm calling an external JSON-API and would like to render the API response in my local response.
Currently I get an error that my items variable is not defined inside of the http request. It seems this is a scope issue but I didn't find a solution.
What is the best way to accomplish this?
var http = require('http');
router.get('/items', function (req, res, next) {
var items;
var RemoteRequest = http.request({
method: 'GET',
path: 'myurl'
}, function (response) {
response.on('data', function (data) {
items = JSON.parse(data);
});
});
RemoteRequest .end();
res.render('new', {items: items} );
// or res.json({items: items});
});

It looks like you are not waiting for the return from your http request, you need to move the res.render('new', {items: items} ); into the callback:
var http = require('http');
router.get('/items', function (req, res, next) {
var items;
var RemoteRequest = http.request({
method: 'GET',
path: 'myurl'
}, function (response) {
response.on('data', function (data) {
items = JSON.parse(data);
res.render('new', {items: items} );
// or res.json({items: items});
});
});
RemoteRequest .end();
});

Related

How to add Get or POST request in the following code

How to add Get or POST request in the following code. My code is running fine. However, how can i add request like GET, POST, PUT OR DELETE
var expect = require('chai').expect;
var request = require('request');
describe('Status and content', function() {
describe ('Main page', function() {
it('status', function(done){
request('http://localhost:3000/', function(error, response, body) {
expect(response.statusCode).to.equal(200);
done();
});
});
it('content', function(done) {
request('http://localhost:3000/' , function(error, response, body) {
//expect(body).to.equal('Hello World');
done();
});
});
});
describe ('About page', function() {
it('status', function(done){
request('http://localhost:3000/', function(error, response, body) {
expect(response.statusCode).to.equal(200);
done();
});
});
});
});
Also, before running this code how i can install and run the JSON server so the api is ready on the localhost. So i do not have to manually do it.
https://medium.com/codingthesmartway-com-blog/create-a-rest-api-with-json-server-36da8680136d?fbclid=IwAR2mEtB6-BKAsSgUto3aOTjx8WmAbsfKB6RkSvHeZbI4Jt0fiqMwbV_QvGw
You can use request module in this way.
let options = {};
options.method = 'GET';
options.uri = 'http://localhost:3000/';
request(options, function(err, res, body){
//....
});
Also for 'POST',
let options = {};
options.method = 'POST';
options.uri = 'http://localhost:3000/';
options.body = {payload};
options.headers = {}; //headers if any
request(options, function(err, res, body) {
//.....
});

sending params through routes

I'm trying to pass some parameters through the URL, i tried to do it this way but it isn't working, the "get(\users:id)" is probably the mistake but i'm not sure whats the correct way:
$.ajax({
type: 'GET',
URL: "'../users/"+id+"'",
success: function(data) {
console.log("success");
}
})
and then i use this route:
app.get('/users/:id', function(req, res) {});
shouldn't this work?
Try this way:
$.ajax({
type: 'GET', URL: "'../users/"+id+"'",
success: function(data) {
console.log("success");
}
}):
An then the route should be:
app.get("/users/:id", function (req, res) {
var id = req.params.id;
});
Your problem seems to be attempting to hit a file system relative path from your client, and the fact that there is no response being sent from your endpoint. Try this (using fetch which is the newer way instead of $.ajax):
fetch('/users/' + id)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
And in your server:
app.get('/users/:id', function(req, res) {
console.log(req.params); // this should be an object containing an `id` param
res.send({});
});

Multiple HTTP async request

I try to fetch data from different HTTP sources but I wasn't able to handle the asynchronous mode even with async...
var express = require('express');
var app = express();
var https = require("https");
var timer = require("./my_modules/timer/timer.js");
var http = require('http');
var bodyParser = require('body-parser');
var async = require('async');
var request = require('request');
//These are my source from API.
//Output is a Json file
var sources = {
cnn: 'https://newsapi.org/v1/articles?source=cnn&sortBy?&apiKey=c6b3fe2e86d54cae8dcb10dc77d5c5fc',
bbc: 'https://newsapi.org/v1/articles?source=cnn&sortBy?&apiKey=c6b3fe2e86d54cae8dcb10dc77d5c5fc',
guardian: 'https://newsapi.org/v1/articles?source=cnn&sortBy?&apiKey=c6b3fe2e86d54cae8dcb10dc77d5c5fc',
othersource: "otherurls..."
};
//I want to push the JSON object in this array
var resultArray = [];
//I setup a https GET request
var getJson = function(url) {
https.get(url, (res) => {
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
result = JSON.parse(body);
//push isn't working...
resultArray.push(result);
});
}).on('error', function(e) {
console.log('Got an error', e);
});
}
app.set('port', (process.env.PORT || 5000));
app.listen(
app.get('port'), () => {
console.log('We are live on port: ', app.get('port'));
getJson(sources.cnn);
});
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.use(function(req, res, next) {
res.setHeader('Content-Type', 'text/plain');
res.status(404).send('Page not found !');
res.status(503).send('Page not found, error 503');
});
console.log("resultArray:" + resultArray);
//resultArray = empty...
What should I do to push the result into my Array?
I couldn't find a way to set up a working callback function to push results into the Array.
Since you're already using the request package, have you tried something as simple as:
request({
url: sources.cnn,
json: true
}, function(error, response, body) {
var articles = body.articles;
// or by case, depending on what you want
// resultArray = resultArray.concat(articles);
resultArray.push({
cnn: articles
});
console.log(resultArray);
});
instead of writing your own getJson function?
Thanks Roby, your request is much clearer !
I have carefully read this really clear and helpful article : https://github.com/maxogden/art-of-node#callbacks
I think I got the logic :
//main function
function getJson(url, callback){
request({
url: url,
json: true,
callback:callback //added this
}, function(error, response, body) {
var articles = body.articles;
callback(articles);
});
}
//this callback function will be passed to the main function as the 2nd parameter
//it's possible to access "resultArray" ONLY from this function
var result = function(e){
resultArray.push(e);
console.log(resultArray);
};
//url and callback are passed as parameter
getJson(sources.cnn, result);
Thanks for the help

Node.js & Express.js/Jade res.render returns res.render is not a function

I haven't been able to find an answer to this error as of yet and am wondering if it has to do with version 4 of Express
controller.js
var request = require('request');
var apiOptions = {
server : "http://localhost:3000"
};
if(process.env.NODE_ENV === 'production') {
apiOptions.server = "https://heroku_path";
}
module.exports.homelist = function(req, res) {
var requestOptions, path;
path = '/api/locations';
requestOptions = {
url: apiOptions.server + path,
method: "GET",
json: {},
qs : {
lng : -117.929835,
lat : 33.614675,
max : 30000
}
};
request(requestOptions, function(err, res, body) {
renderHomepage(req, res, body);
});
var renderHomepage = function(req, res, body) {
res.render('jade-template', {
title: 'I'm a main title',
pageHeader: {
title: 'I'm a title',
strapline: 'I'm a strapline'
},
locations: body,
sidebar: 'yadda yadda'
});
};
The homelist function gets called from my routes.js which is then where my API gets called from my request with the query found in requestOptions.
however when the request callback is fired and renderHomepage in invoked with the API variable body I get the error:
res.render('jade-template', {
^
TypeError: res.render is not a function
All my routes are set up and tested fine. Does anyone have a solution for this?
The res argument in the renderHomepage function (the request's callback) is not the same as the res of the express route!
Change your call the request to something like:
request(requestOptions, function(err, serverRes, body) {
renderHomepage(req, res, body);
});
Then the response to your request to /api/locations is serverRes, and the response you send to your client is res.

$.ajax is not a function when being called

for some reason when I run npm start and I hit the browser, I am getting this stack trace with this error.
TypeError: $.ajax is not a function
at getLocationFromIp (G:\Github\Expressjs\nodetest1\routes\index.js:13:7)
at G:\Github\Expressjs\nodetest1\routes\index.js:24:14
Would someone be able to tell me why? Here is my code. Thanks!
var express = require('express');
var router = express.Router();
var externalip = require('external-ip');
var $ = require('jquery');
getLocationFromIp = function() {
$.ajax({
url:"freegeoip.net/json/",
type: "GET",
data: null,
dataType: "json",
success: function(){console.log("success!")}
});
}
router.get('/', function(req, res) {
var ip = getLocationFromIp();
res.render('index', { 'ip' : "hi"});
});
See the documentation:
For jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by tools such as jsdom. This can be useful for testing purposes.
var externalip = require('external-ip');
require("jsdom").env("", function(err, window) {
if (err) {
console.error(err);
return;
}
var $ = require("jquery")(window);
function getLocationFromIp() {
$.ajax({
url: "freegeoip.net/json/",
type: "GET",
data: null,
dataType: "json",
success: function() {
console.log("success!")
},
error: function() {
console.log("error", arguments[2])
}
});
}
var ip = getLocationFromIp();
console.log(ip);
});
You'd probably be better off using an HTTP library designed to work with Node from the outset, such such as request.
If you are using jquery to just make a http request, you can probably use the http or request node module to do that instead.
var express = require('express');
var router = express.Router();
var externalip = require('external-ip');
var http = require('http');
getLocationFromIp = function(done) {
var options = {
host: "freegeoip.net",
port: 80,
path: "/json"
};
var request = http.get(options, function(response) {
var result = "";
var responseCode = response.statusCode;
response.on('data', function(data) {
result += data;
});
response.on('end', function() {
if(responseCode >= 400)
return done(result, null);
else
return done(false, JSON.parse(result));
});
});
request.on("error", function(error){
return done("Error handling error", null);
});
request.end();
}
router.get('/', function(req, res) {
var ip = getLocationFromIp(function(error, ip){
res.render('index', { 'ip' : "hi"});
});
});

Categories