I am making an api call and recieving the data, however, I am having trouble sending the data back to my js file. I tried using res.send but I am getting an error. I can't seem to figure out how to send the information back to the javascript file. (I took my key out of the request link. For security reasons, however, I am getting the data back from the api call). The only problem I am having is returning the data to the frontend javascript file.
This is the Javascript file that sends the original request:
/ ********** options button function makes api call to get selected cities forecast *****************
function getCityForecast(e){
var id = document.getElementById('cities');
var getValue = id.options[id.selectedIndex].value;
var suffix = getValue + ".json";
var newObj = JSON.stringify({link : suffix});
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:3000/", true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.send(newObj);
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
console.log(xhr.response);
console.log('recieved');
} else {
console.log('error');
}
}
}
My server.js file looks like this:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var http = require('http');
var path = require('path');
var request = require('request');
// ****************** Middle Ware *******************
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(__dirname + '/public'));
var retrievedString;
// **************** Post Request *******************
app.post('/', function(req, res){
var link = "http://api.wunderground.com/api/key/forecast";
retrievedString = link.concat(req.body.link);
request = http.get(retrievedString , function(res){
var body = '';
res.on('data', function(data){
body += data;
});
res.on('end', function(){
var parsed = JSON.parse(body);
console.log(parsed.forecast.txt_forecast);
res.send(parsed.forecast.txt_forecast);
});
})
.on('error', function(e) {
console.log("Got error: " + e.message);
});
});
app.listen(3000, function() { console.log('listening')});
You are overloading the definition of the variable res which is also what you called the response variable for your Express route handler method. In the callback function of the request, use a different name for that variable - for example:
request = http.get(retrievedString , function(resDoc){
Related
Send a parameter(URL) from another script through recursion to this script.
var express = require('express');
var request = require('request');
var cheerio = require('cheerio');
var mongodb = require('mongodb');
var app = express();
var MongoClient = mongodb.MongoClient;
// Connection URL. This is where your mongodb server is running.
var murl = 'mongodb://localhost:27017/getData';
url = '';
app.get('/getData', function(req, res){
firstCall(req,res)
//console.log("cookie",req.cookies);
})
var firstCall = function(req, res, data){
console.log("URL: ", url);
res.send('Check your console!');
}
app.listen('3000')
console.log('Magic happens on port 3000');
module.exports = function(app) {
app.get('/getData', function() {});
};
I want this code to act as backbone or logic board. And some other file should be able to trigger this logic board file by adding the URL to this file.
Like we pass parameters to function to call. How do I do it here.
I am a CS student with a strong Java background, and javascript is resulting to be a challenging but fun experience so far, that is until I ran into the situation where I tried to use my own modules to return values that require the program to wait for the completion of some procedure before returning.So far no-one from any forum that I have posted this question on has been able to give an actual code fix to the problem, they have referred me to read further material that is not related to the problem at hand. Would anyone please read the code and provide a working correct standard solution to the problem I am facing?
Here is the code, a simple nodes server application, app.js and a weather module, weatherApp.js that uses an user provided zip code and returns a weather forecast in the area.
here is the code:
weatherApp.js
// The required modules.
var http = require("http");
var https = require("https");
//result object
var resultSet = {
googleRequestUrl:"",
forecastIOrequest:"",
latitude :"",
longitude:"",
localInfo:"",
weather:"",
humidity:"",
pressure:"",
time:""
};
//print out error messages
function printError(error){
console.error(error.message);
}
//Forecast API required information:
//key for the forecast IO app
var forecast_IO_Key = "bb9aac7c57877f8f5fab339e3b55669a";
var forecast_IO_Web_Adress = "https://api.forecast.io/forecast/";
//Create Forecast request string function
function createForecastRequest(latitude, longitude){
var request = forecast_IO_Web_Adress + forecast_IO_Key + "/"
+ latitude +"," + longitude;
return request;
}
//Google GEO API required information:
//Create Google Geo Request
var google_GEO_Web_Adress = "https://maps.googleapis.com/maps/api/geocode/json?address=";
function createGoogleGeoMapRequest(zipCode){
var request = google_GEO_Web_Adress+zipCode + "&sensor=false";
return request;
}
// 1- Need to request google for geo locations using a given zip
function connectToGoogleGEO(zipCode, afterCallback){
var googleRequest = https.get(createGoogleGeoMapRequest(zipCode), function(response){
//saving the Google request URL
resultSet.googleRequestUrl = createGoogleGeoMapRequest(zipCode);
var body = "";
var status = response.statusCode;
//a- Read the data.
response.on("data", function(chunk){
body+=chunk;
});
//b- Parse the data.
response.on("end", function(){
if(status === 200){
try{
var googleReport = JSON.parse(body);
resultSet.latitude = googleReport.results[0].geometry.location.lat;
resultSet.longitude = googleReport.results[0].geometry.location.lng;
resultSet.localInfo = googleReport.results[0].address_components[0].long_name + ", " +
googleReport.results[0].address_components[1].long_name + ", " +
googleReport.results[0].address_components[2].long_name + ", " +
googleReport.results[0].address_components[3].long_name + ". ";
// callback to forecast IO.
afterCallback(resultSet.latitude, resultSet.longitude);
}catch(error){
printError(error.message);
}finally{
// nothing here
}
}else{
printError({message: "Error with GEO API"+http.STATUS_CODES[response.statusCode]})
}
});
});
}
function connectToForecastIO(latitude,longitude){
var forecastRequest = https.get(createForecastRequest(latitude,longitude),function(response){
resultSet.forecastIOrequest = createForecastRequest(latitude,longitude);
var body = "";
var status = response.statusCode;
//read the data
response.on("data", function(chunk){
body+=chunk;
});
//parse the data
response.on("end", function(){
try{
var weatherReport = JSON.parse(body);
resultSet.weather = weatherReport.currently.summary;
resultSet.humidity = weatherReport.currently.humidity;
resultSet.temperature = weatherReport.currently.temperature;
resultSet.pressure = weatherReport.currently.pressure;
resultSet.time = weatherReport.currently.time;
}catch(error){
printError(error.message);
}finally{
console.log(resultSet);
}
});
});
}
function get(zipCode){
var results = connectToGoogleGEO(zipCode, connectToForecastIO);
return results;
}
//define the name of the outer module.
module.exports.get = get;
And here is the server code:
app.js
var express = require("express");
var weatherApp = require("./weatherApp.js");
var path = require("path");
var http = require("http");
var app = express();
//creating routes
//The home
app.get("/", function(req, res){
res.redirect("/weather");
});
app.get("/weather", function(req, res){
res.sendFile(path.join(__dirname + "/index.html"));
});
//------------------------------------------------------
//The resources, css, web js files, images etc.
app.get("/StyleSheets/style.css", function(req, res){
res.sendFile(path.join(__dirname + "/StyleSheets/style.css"));
});
app.get("/webScripts/app.js", function(req, res){
res.sendFile(path.join(__dirname + "/webScripts/app.js"));
});
app.get("/webImages/swirl_pattern.png", function(req, res){
res.sendFile(path.join(__dirname + "/webImages/swirl_pattern.png"));
});
//-------------------------------------------------------
//other requests
app.get("/zipcode.do", function(req, res){
var zipcode = req.query["zipcode"];
var response = "No report Available";
function getReport(zipCode, callback){
response = weatherApp.get(req.query["zipcode"]);
}
getReport(zipcode, ()=>{
res.send("<p>" + response+ "</p>");
});
});
//any other entry thats not listed as a valid to request
app.get("/:title", function(req,res){
var title = req.param.title;
if(title === undefined){
var status = res.status(503);
res.send("This page does not exists" + '"' + http.STATUS_CODES[503] + '"');
}else{
res.send(title);
}
});
app.listen(3000, function(){
console.log("Server running at port: 3000")
});
The main issue I am having right now is:
The program is not returning anything from the module even when final console.log in the weather module prints the right resultSet object.
The server is not waiting for the module to return, and continues to print no data.
Can someone provide a working fix to any of these problems I would be really grateful, This has really hindered my progress and broken down my morale a little :(
Your problem is that you are using asynchronous functions as if they were synchronous.
It might not be the only issue here, but this function is particularly problematic:
function get(zipCode){
var results = connectToGoogleGEO(zipCode, connectToForecastIO);
return results;
}
connectToGoogleGEO() calls the asynchronous https.get() function and does not return the data that is retrieved from Google. You need to rewrite your code so that it does not expect the data to be returned by the function. Instead, you need to pass a callback that will handle the data.
Take care to know when you are calling asynchronous functions and how their callbacks work. It is fundamental when working with Node.js
When I type somedomain.com/some_api_url?_var1=1 into a browser, the response is {"1":"descriptive string"}, where 1 is a numerical index variable whose value could range from 1 to n. And where "descriptive string" is some text that summarizes what the index represents.
How can I integrate the JSON response from the somedomain.com/some_api_url?_var1=1 api url into the very simple Node.js and Express.js example below?
For testing purposes, the very simple app.js shown below returns "Hello World" when the user requests http : // localhost : 3000 from their web browser. What specific changes need to be made to the code below so that the web browser responds to the request with:
Index is: 1
Description is: descriptive string
instead of responding with "Hello World"?
Here is the current code for app.js:
var express = require('express');
var http = require('http');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Here is my current attempt, which results in the console printing Got a response: undefined, and with the browser remaining hung up because nothing is returned to the browser as a response:
var express = require('express');
var http = require('http');
var app = express();
app.get('/', function (req, res) {
var url = 'somedomain.com/some_api_url?_var1=1';
http.get(url, function(res){
var body = '';
res.on('data', function(chunk){
body += chunk;
});
res.on('end', function(){
var fbResponse = JSON.parse(body);
console.log("Got a response: ", fbResponse.picture);
});
}).on('error', function(e){
console.log("Got an error: ", e);
});
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
The get example code was adapted from the example at this link.
You actually forgot to return response res.send(data). Change you endpoint code like this. Also use different variable name for internal response object. I am using response here.
app.get('/', function (req, res) {
var url = 'somedomain.com/some_api_url?_var1=1';
http.get(url, function(resonse){
var body = '';
resonse.on('data', function(chunk){
body += chunk;
});
resonse.on('end', function(){
var body = JSON.parse(body);
var text = '';
for (var key in body){
text += 'Index is: ' + key +
'\nDescription is: ' + body[key]
}
// The Description is: "descriptive string"
console.log("Got a response: ", fbResponse);
res.send(text);
});
}).on('error', function(e){
console.log("Got an error: ", e);
});
});
Try this code with express 4.14.0
As #Zohaib-Ijaz pointed out, res is redefined and won't work for the res.send without a rename. This code also calls itself for demo purposes (so you can ignore app.get('/some_api_url', for the moment.
Then once the http.get is done, work with the object and print as you like. Keep in mind this code is not defensive against errors in the JSON.
var express = require('express');
var http = require('http');
var app = express();
const PORT = 3000;
app.get('/', function (req, res) {
var url = `http://localhost:${PORT}/some_api_url?_var1=1`;
http.get(url, function (resInner) {
var body = '';
resInner.on('data', function (chunk) {
body += chunk;
});
resInner.on('end', function () {
var fullResponse = JSON.parse(body); // {"343",:"I've heard 344 is more"}
// code to pair the keys with their data in plain js
var indexKeys = Object.keys(fullResponse);
var replies = indexKeys.map((key) => {
return `Index is ${key}\nDescription is ${fullResponse[key]}`;
});
//note this injection of a <pre> tag is just so modern browsers
// will respect the newlines. it is not an HTML document or JSON
res.send(
`<pre>${replies.join("\n")}</pre>`
);
});
}).on('error', function (e) {
console.log("Got an error: ", e);
});
});
app.get('/some_api_url', (req, res) => {
var var1 = req.query.var1 || "343";
var value = `I've heard ${parseInt(var1) + 1} is more`;
var reply = {};
reply[var1] = value;
res.send(JSON.stringify(reply));
});
app.listen(PORT, function () {
console.log(`Example app listening on port ${PORT}!`);
});
You seem to be mixing up Express, native HTTP module, and HTTP client.
Here is the serverside code for sending the response you are looking for.
var express = require('express');
var http = require('http');
var app = express();
// our "database"
var database = ['APPLE', 'BOOK', 'CAT', 'DOG', 'ELEPHANT'];
app.get('/', function (req, res) {
// apply query parsing only of the query parameter is specified
if ('itemId' in req.query) {
var itemId = req.query.itemId;
// index less than 0 will not yield anything from our "database"
if (itemId < 0) {
res.status(400).send('Invalid item id');
// the item index corresponds to one of the items in the "database"
} else if (itemId < database.length) {
var result = 'Index: ' + itemId + '<br>Description: ' + database[itemId];
res.send(result);
// index exceeds the size of the array, so nothing will be found
} else {
res.status(404).send('Item not found');
}
// render the default homepage
} else {
res.send('Request format: http://localhost:3000/?itemId=n');
}
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
To see it in action, load http://localhost:3000/?itemId=0 in the browser. Valid itemId values are 0 to 4.
I'm trying to send a JSON object from javaScript to node.js server. I'm using a standard XMLHttpRequest to send it from javascript and a standard node.js code.
Two codes seem to be communicating normally however the node.js always gives me an empty JSON object. I'm not really sure what am I doing wrong.
This is my javascript code:
<html>
<head>
<script>
function xhrPost() {
var data = {"name":"John", "time":"2pm"};
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "http://[serverIP]:8080/addUser");
xhr.setRequestHeader("cache-control", "no-cache");
xhr.setRequestHeader("content-type", "application/json;charset=UTF-8");
xhr.send(JSON.stringify(data));
}
</script>
</head>
<body onload="xhrPost()">
</body>
</html>
and this is my node.js code:
var express = require("express");
var myParser = require("body-parser");
var app = express();
app.use(myParser.urlencoded({extended : true}));
app.post("/addUser", function(request, response) {
console.log(request.body); // this line allways produce {}
response.send("Message received.");
response.end();
});
app.listen(8080);
You have to use myParser.json() as a middleware. See more about it in https://github.com/expressjs/body-parser#bodyparserjsonoptions
After following line:
var myParser = require("body-parser");
You should add on more line as:
var myParser = require("body-parser");
app.use(myParser.json());// parse application/json
This was the most helpful stackoverflow page to solve my problem as well.
I was trying to get form fields, formulate them into a JSON on the client, then send to the server to use the fields for a MySQL call to a separate database.
Object {name: "", reps: "1", weight: "1", date: "", lbs: "0"}
I was able to get the object logging correctly on the client, yet every time I tried to send the data to the server,
console.log(req.body);
Would always return on the server as either
{}
undefined
Server side my setup with functioning data passing is
var express = require('express');
var mysql = require('./dbcon.js');
var app = express();
var handlebars = require('express-handlebars').create({defaultLayout:'main'});
var request = require('request');
var myParser = require("body-parser");
var async = require('async');
app.set('view engine', 'handlebars');
app.set('port', Number(process.env.PORT || 3000));
app.use(myParser.json());
app.use(express.static('public'));
app.engine('handlebars', handlebars.engine);
On my client side js file, I have a function upon form submit that does:
var data = {
"name":document.getElementById("fname").value,
"reps":document.getElementById("freps").value,
"weight":document.getElementById("fweight").value,
"date":document.getElementById("fdate").value,
"lbs":bool
};
...
req.open("POST", "/insert", true);
req.setRequestHeader("content-type", "application/json;charset=UTF-8");
...
req.send(JSON.stringify(data));
I'm going through a Node, Express, & Socket.io chat tutorial. I decided to use Redis to store the chat history and have successfully set it up so that my information is correctly posting to the database. I am now trying to access that information to use on the client-side (in this case I'm trying to access the list of users currently in the chat so I can show them to the side of the chat). I am using $.getJSON to make a GET request. Right now I have it setup so that the file it tries to access only has this JSON object : {"dog" : "2","cat":"3"} just to test it, and that is working, but I'm not sure where to go from there because anytime I try adding a function into that file, even if I specify to return a JSON object and call that function, the request stops returning the correct information.
For example I tried :
var data = function(){
return {"dog" : "2","cat":"3"}
}
data();
and that doesn't return anything ( I understand that when I make a GET request the function isn't run, but it doesn't even return that text, and if it doesn't run a function than I'm not sure how I can access redis from this file)
Here's what I'm thinking:
var redis = require('redis')
//figure out how to access the redis client that I have at localhost:6379, something like var db = redis.X
//and then call (for example) db.smembers('onlineUsers') and be returned the object which I can iterate through
Here's my relevant code:
server.js:
var jade = require('jade');
var PORT = 8080;
var redis = require('redis');
var db = redis.createClient();
var pub = redis.createClient();
var sub = redis.createClient();
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(PORT, function(){
console.log("Now connected on localhost:" + PORT)
});
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.set("view options", {layout: false});
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res){
res.render('home');
});
io.sockets.on('connection', function(client){
sub.subscribe("chatting");
sub.on("message", function (channel, message) {
console.log("message received on server from publish");
client.send(message);
});
client.on("sendMessage", function(msg) {
pub.publish("chatting",msg);
});
client.on("setUsername", function(user){
pub.publish("chatting","A new user in connected:" + user);
db.sadd("onlineUsers",user);
}
);
client.on('disconnect', function () {
sub.quit();
pub.publish("chatting","User is disconnected :" + client.id);
});
});
script.js:
$(document).ready( function(){
$client = io.connect();
initialize();
});
var setUsername = function(){
var username = $("#usernameInput").val();
if (username)
{
var user = username;
$client.emit('setUsername', username);
$('#chatControls').show();
$('#usernameInput').hide();
$('#usernameSet').hide();
showCurrentUsers();
}
}
var showCurrentUsers = function(){
$('#list_of_users').empty();
$.getJSON('getusers.js', function(data){
for (var i = 0; i < data.length; i++){
$('list_of_users').append("<li>"+data[i]+"</li>")
}
})
}
var sendMessage = function(){
var msg = $('#messageInput').val();
var username = $("#usernameInput").val();
if (msg)
{
var data = {msg: msg, user: username}
$client.emit('message', data);
addMessage(data);
$('#messageInput').val('');
// populate(username,msg);
}
}
var addMessage = function(data) {
$("#chatEntries").append('<div class="message"><p>' + data.user + ' : ' + data.msg + '</p></div>');
}
// var populate = function(username,msg) {
// var data ;
// }
var initialize = function(){
$("#chatControls").hide();
$("#usernameSet").on('click', setUsername);
$("#submit").on('click',sendMessage);
showCurrentUsers();
}
and right now all that the getusers.js file has in it is:
{"dog" : "2","cat":"3"}
It looks like you're expecting your call to $.getJSON to load and execute the javascript it loads. It doesn't work this way. You need to make a node endpoint (via a route) which renders the JSON. The node endpoint would then do the data manipulation / querying redis:
Node:
In routes.js:
app.get('/chatdata', ChatController.getChatData);
In ChatController.js (manipulate, create the data as you like here)
exports.getChatData = function (req, res) {
var data = function(){
return {"dog" : "2","cat":"3"}
};
res.JSON(data);
};
Front-end
$.getJSON('getChatData', function(data){
//...
})
I think you need to setup a route to handle the GET request that $.getJSON makes, or if getusers.js is in the /public directory, then you need to modify your $.getJSON call as follows:
$.getJSON('http://localhost:8080/public/getusers.js', function(data){
Ok, it looks like it is a problem with your getusers.js file. $.getJSON seems to prefer double quotes. Try formatting it like this:
{
"dog" : "2",
"cat" : "3"
}
Also, try using this to display the data:
$.getJSON('getusers.js', function(data){
var items = [];
$.each( data, function( key, val ) {
items.push("<li id='" + key + "'>" + val +"</li>");
});
$('#list_of_users').append(items.join(""));
});