I'm a new developer learning how to work with API's and I've run into this error a few times now that keeps crashing Node:
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at IncomingMessage.<anonymous> (/Users/SA/Desktop/pokeApp/app.js:13:34)
at IncomingMessage.emit (events.js:314:20)
at IncomingMessage.Readable.read (_stream_readable.js:513:10)
at flow (_stream_readable.js:986:34)
at resume_ (_stream_readable.js:967:3)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
I'm not really sure how to resolve it or what the problem is exactly... my JS code looks like this:
const express = require("express");
const https = require("https");
const app = express();
app.get("/", (req,res) => {
const url = "https://pokeapi.co/api/v2/pokemon/1/";
https.get(url, function(response){
console.log(response.statusCode);
response.on("data", (data) =>{
const pokemon = JSON.parse(data);
console.log(pokemon);
})
})
res.send("server running");
})
app.listen(3000, () => {
console.log("Port 3000");
})
This is basically the same setup I used for a weatherAPI and had no issues.
I also checked the JSON with JSON lint to see if there were any problems and it came back okay.
You need to wait for the full response to come in - it's a large file, so it may not come in all at once:
https.get(url, function(response){
let result = '';
response.on("data", (data) =>{
result += data;
});
response.on('end', () => {
const pokemon = JSON.parse(result);
console.log(pokemon);
});
})
Related
I am attempting to grab data from an API from openWeatherAPI with a correct api key and query (I checked with Postman to ensure the call is correct), but ran into a syntax error. When I try to call the on() function inside of my https.get callback function, I am met with the following error in my terminal:
response.on("data", (data) => {
^
TypeError: Cannot read properties of undefined (reading 'on')
at ClientRequest.<anonymous> (C:file-path\api-prac\app.js:16:18)
at Object.onceWrapper (node:events:628:26)
at ClientRequest.emit (node:events:513:28)
at HTTPParser.parserOnIncomingClient [as onIncoming] (node:_http_client:693:27)
at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)
at TLSSocket.socketOnData (node:_http_client:534:22)
at TLSSocket.emit (node:events:513:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at TLSSocket.Readable.push (node:internal/streams/readable:228:10)
My code:
const express = require("express");
const https = require("https");
const app = express()
// what should happen when user tries to go to home page
app.get("/", function(req, res) {
const url = "https://api.openweathermap.org/data/2.5/weather?q=London&appid=my-api-key";
https.get(url, function(req, response) {
console.log("blah blah repsonse");
response.on("data", (data) => {
console.log(data);
// const weatherDatta = JSON.parse(data)
/* extra code will be put here to send a response */
})
});
res.send("server is up");
}
app.listen(3000, function() {
console.log("app running on server 3000");
})
I tried looking at the documentation shown on the https://nodejs.org/api/https.html website, but was unable to find anything that helped outside of what I was already doing with my code.
The arguments for your https.get() callback are wrong. It should be this:
https.get(url, function(response) {
response.on('data', ...);
});
There is no second argument so when you try to make one, it's undefined and does not work.
Code example in the doc here.
Note also that there is no guarantee that you get the entire response in the first data event. The response may arrive in chunks so if you're trying to get the whole response, you should be accumulating all the data events and then processing them all in the end event. And, you should be handling errors in multiple places:
https.get(url, function(response) {
let result = "";
response.on('data', data => {
result += data.toString();
}).on('end', () => {
try {
let weatherData = JSON.parse(result);
// use the weatherData here
} catch(e) {
console.log(e);
// handle JSON parsing error here
}
}).on('error', err => {
console.log(err);
// handle http request error here
});
});
Note, using an http request library such as got() or node-fetch() or even fetch() which is built-in to the newest versions of nodejs will make this code much simpler because they will retrieve the entire response for you and are promise based which makes a number of things including error handling much simpler.
Note how much simpler this is with the got() library.
got(url).json().then(weatherData => {
// use weatherData here
}).catch(err => {
console.log(err);
// handler error here
});
I get a Syntax Error: "Unexpected end of JSON input at JSON.parse () at IncomingMessage.". I don't know why I am getting that error.
Here is my code:
const express = require("express");
const https = require("http");
const app = express();
app.get("/", function(req, res){
const url = "http://api.openweathermap.org/data/2.5/forecast?q=Accra&id=524901&appid=18a15324259a5d6f30f8e6610f8a4310";
https.get(url, function(response){
response.on("data", function(data){
const weatherData = JSON.parse(data);
console.log(weatherData);
// console.log(data);
});
});
});
Here you are trying to get the data before confirming wether it's completely received or not.
instead of reading at the on('data'), wait for on('end')
something like this :
body = [];
req.on('data', (chunk) => {
// Storing the chunk data
body.push(chunk);
});
req.on('end', () => {
// combining and parsing the chunk data to normal data
const parsedBody = Buffer.concat(body).toString();
const message = parsedBody.split('=')[1];
// Now you can parse the **message** to find the data
console.log(JSON.parse(message))
});
This will collect and parse the data once after collecting all the chunks.
How to get data from my function Data() instead of JSON PLACE HOLDER mock API using HTTPS/HTTP node module and how to make an endpoint of this get data HTTP/HTTPS module to utilize response in front end just like Angular?
My mock backen.js file:
const https = require('https');
https.get(Data.data, res => {
let data = [];
const headerDate = res.headers && res.headers.date ? res.headers.date : 'no response date';
console.log('Status Code:', res.statusCode);
console.log('Date in Response header:', headerDate);
res.on('data', chunk => {
data.push(chunk);
});
res.on('end', () => {
console.log('Response ended: ');
const users = JSON.parse(Buffer.concat(data).toString());
for(user of users) {
console.log(`Got user with id: ${user.id}, name: ${user.name}`);
}
});
}).on('error', err => {
console.log('Error: ', err.message);
});
function Data() {
var data = {};
........
return data;
}
Your time and help will be really appreciated. Thanks :)
Hurray! I got it using the following code and Express in node js. I simply call my custom method that creates data into an express "get" endpoint. When I hit the end point the response will be my custom method result.
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/data', (req, res) => {
res.send(
getDashboardData());
});
app.listen(3000, () => {
console.log('server is listening on port 3000');
});
function Data() {
var data = {};
..........
//console.log(JSON.stringify(data));
return JSON.stringify(data);
}
i am using openweathermap API. When i try to parse response data to json it gives me an error.
i dont know what to do about this can anyone help??
CODE:
const express = require("express");
const https = require("https");
const app = express();
app.get("/", function (req, res) {
const url = "https://api.openweathermap.org/data/2.5/forecast?appid=faa02526fbe231fa9d2dc1aa991a26f2&q=London";
https.get(url, function (response) {
console.log(response.statusCode);
response.on("data", function (data) {
JSON.parse(data);
});
});
res.send("upp and running");
});
app.listen(3000, function () {
console.log("up and running");
});
console output:
up and running
200
undefined:1
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at IncomingMessage.<anonymous> (E:\webdevel\WeatherProject\app.js:14:18)
at IncomingMessage.emit (events.js:375:28)
at IncomingMessage.Readable.read (internal/streams/readable.js:500:10)
at flow (internal/streams/readable.js:982:34)
at resume_ (internal/streams/readable.js:963:3)
at processTicksAndRejections (internal/process/task_queues.js:82:21)
[nodemon] app crashed - waiting for file changes before starting...
Your problem is that you think that .on("data", handler) will only be called once with the full reply. That's not how the API works, check the documentation.
Basically, the response body is streamed in. The data event can be emitted many times, each with a chunk of the body response. Therefore, buffer all the data and wait for the response to finish:
https.get(url, function (response) {
console.log(response.statusCode);
let resultData = '';
response.on('data', data => resultData += data);
response.on('end', () => {
// Now we got the whole response body
JSON.parse(resultData);
});
});
I am trying to post data from my form to MailChimp API server with node.js and express. However, I am getting an error message that seems strange to debug. I have checked my index.html file and all is well there. Please help me figure out a solution or point me in the right direction. Kindly check out my code below:
const express = require("express");
const bodyParser = require("body-parser");
const https = require("https");
const app = express();
app.use(bodyParser.urlencoded({extended:true}));
app.use(express.static("public"));
app.listen(3000, function(){
"Server is running on Port 3000!"
});
app.get("/", function(req, res){
res.sendFile(__dirname + "/signup.html");
});
app.post("/", function(req, res){
const firstName = req.body.firstName;
const lastName = req.body.lastName;
const email = req.body.email;
console.log(firstName, lastName, email);
var data= {
members: [
{
email_address : email,
status : "subscribed",
merge_fields : {
FNAME : firstName,
LNAME : lastName
}
}
]
};
var jsonData = JSON.stringify(data);
const url ="https://us10.api.mailchimp.com/3.0/lists/{apikey}";
const options = {
method: "post",
auth: "xxxx:xxxx"
}
const request= https.get(url, options, function(response){
response.on("data", function(data){
console.log(JSON.parse(data));
})
})
request.write(jsonData);
request.end();
});
This is the error I am getting.
events.js:200
throw er; // Unhandled 'error' event
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at write_ (_http_outgoing.js:594:17)
at ClientRequest.write (_http_outgoing.js:586:15)
at C:\Users\Iredafe\Desktop\Web Development practice\Email-List\app.js:48:9
at Layer.handle [as handle_request] (C:\Users\Iredafe\Desktop\Web Development practice\Email-List\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\Iredafe\Desktop\Web Development practice\Email-List\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\Iredafe\Desktop\Web Development practice\Email-List\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\Users\Iredafe\Desktop\Web Development practice\Email-List\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\Iredafe\Desktop\Web Development practice\Email-List\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\Users\Iredafe\Desktop\Web Development practice\Email-List\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\Iredafe\Desktop\Web Development practice\Email-List\node_modules\express\lib\router\index.js:275:10)
Emitted 'error' event on ClientRequest instance at:
at writeAfterEndNT (_http_outgoing.js:649:7)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
code: 'ERR_STREAM_WRITE_AFTER_END'
}
[nodemon] app crashed - waiting for file changes before starting...
You can use axios for simplicity.
const axios = require('axios');
const headers = {
'Content-Type': 'application/json',
'Authorization': 'JWT fefege...'
}
axios.post(url,postPayload,headers)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
I just found the answer. It was a bug in my code. I am using the native https method in Node hence I ought not to use https.get here:
const request= https.get(url, options, function(response){
response.on("data", function(data){
console.log(JSON.parse(data));
})
})
request.write(jsonData);
request.end();
the correct code that solved the problem was using the http.request instead of http.get:
const request= https.request(url, options, function(response){
response.on("data", function(data){
console.log(JSON.parse(data));
})
})
request.write(jsonData);
request.end();
Hope it helps someone in the future!