1
votes

app.js:

const express = require("express");
const https = require("https");
const app = express();

const port = 3000;

app.get("/",function(req,res){
  const url ="https://maps.googleapis.com/maps/api/geocode/jsonaddress=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY;
      console.log(response.statusCode);
    response.on("data",function(data){
      var jatin=JSON.parse(data);
      console.log(jatin);
  })
})

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

Error on Console

app.listen(3000,function(){ console.log("server started on port 3000"); })

server started on port 3000 200 undefined:26 "long_name"

SyntaxError: Unexpected end of JSON input at JSON.parse () at IncomingMessage. (/home/jatin/Downloads/full_stack/Web-Development/maps/app.js:11:21) at IncomingMessage.emit (events.js:189:13) at IncomingMessage.Readable.read (_stream_readable.js:487:10) at flow (_stream_readable.js:931:34) at resume_ (_stream_readable.js:912:3) at process._tickCallback (internal/process/next_tick.js:63:19) [nodemon] app crashed - waiting for file changes before starting

The output is visible when I run it on browser but on the console it throws an error. For some reason JSON.parse() isn't working as expected.

I am trying to make a geocoding API call and in response, it gives me a JSON output... which when I enter it as a URL on the browser the expected output is received But when app.js is run on a node express server and when I hit my localhost:3000 I am getting the console error

Apparently the JSON.parse("data") is working but stops unexpectedly. Which leads to error.

1
Can you please add you response data structure ?Jasdeep Singh
"data" gets triggered for each chunk in the stream. You have to collect all chunks, then combine them into the whole response, then call JSON.parse on it. Or use a library that supports parsing streams (e.g. fetch)Jonas Wilms
response.on("data",function(data){ var jatin=JSON.parse(data); console.log(jatin); --------------------------------------------------------------------------------------------------------that is what I am doing... collecting an entire stream of response in var JatinMahir Gada
try logging data without JSON.parse share the log, response may be not a valid parse-able JSON.fdevansvd
Kindly add logged data in your question itself. It will be helpful to debug.Harshit

1 Answers

0
votes

You need to have your code to perform JSON.parse on end event instead, like this example form the documentation:

http.get('http://nodejs.org/dist/index.json', (res) => {
  const { statusCode } = res;
  const contentType = res.headers['content-type'];

  let error;
  if (statusCode !== 200) {
    error = new Error('Request Failed.\n' +
                      `Status Code: ${statusCode}`);
  } else if (!/^application\/json/.test(contentType)) {
    error = new Error('Invalid content-type.\n' +
                      `Expected application/json but received ${contentType}`);
  }
  if (error) {
    console.error(error.message);
    // Consume response data to free up memory
    res.resume();
    return;
  }

  res.setEncoding('utf8');
  let rawData = '';
  res.on('data', (chunk) => { rawData += chunk; });
  res.on('end', () => {
    try {
      const parsedData = JSON.parse(rawData);
      console.log(parsedData);
    } catch (e) {
      console.error(e.message);
    }
  });
}).on('error', (e) => {
  console.error(`Got error: ${e.message}`);
});

Notice that this is http.get, but it should be the same for https.get, so in your code the on('data') should be used to assemble the chunks before your perform JSON.parse() on it.

const express = require("express");
const https = require("https");
const app = express();

const port = 3000;

app.get("/", function(req, res) {
  const url = "API_URL";
  https.get(url, function(response) {
    console.log(response.statusCode);
    let body = "";
    response.on("data", function(data) {
      body += data;
    });

    response.on("end", function() {
      console.log(JSON.parse(body));
    });
  });
  res.end("End data response");
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

basically .on('end', callback') and .on('data', callback') are event listener to data receive and request end events, and to be able to handle your requests response in node when using http(s).get you have to attache an event listener on data event which is invoked every time your request receives a chunk of the request response, and once the request ended by the service the event end will be invoked stating that there is no more data from the server requested hence the request ended.

as stated in the documentation:

The callback must take care to consume the response data for reasons stated in http.ClientRequest section.