Cannot set headers after they are sent to client Expressjs router - javascript

I'm getting error cannot set headers on express js, I think the problem is have to write setHeader, i was set but stil can't, this my code:
router.get('/cek', (req, res) => {
const child = execFile(commandd, ['-c', 'config', 'GSM.Radio.C0']);
child.stdout.on('data',
function (data) {
value = (JSON.stringify(data));
x = value.split('.');
y = JSON.stringify(x[2])
result = y.replace(/\D/g, "");
res.setHeader('Content-Type', 'text/html');
res.send(result);
}
);
child.stderr.on('data',
function (data) {
console.log('err data: ' + data);
}
);
});
I tired to fixing this error for two days, but still cannot, anybody can help?

As stated by Frederico Ibba, this is usually caused after res.send is sent and there is still data being processed... Your workaround for this may simply be to receive all the data before sending it out using res.send. You can try this.
async function executeCommand() {
return new Promise((resolve, reject) => {
const child = execFile(commandd, ['-c', 'config', 'GSM.Radio.C0']);
child.stdout.on('data',
function (data) {
value = (JSON.stringify(data));
x = value.split('.');
y = JSON.stringify(x[2])
result = y.replace(/\D/g, "");
resolve(result);
}
);
child.stderr.on('data',
function (err) { // Renamed data for err for clarification
reject(err);
}
);
});
}
router.get('/url', async (req, res) => {
try {
const result = await executeCommand();
res.setHeader('Content-Type', 'text/html');
res.send(result);
} catch(error) {
// There was an error. I'm throwing a 500
res.sendStatus(500);
}
});
Note that this will be effective only if you are confident that the data is being fired once, as indicated by skirtle

Related

Redis get function

I'm getting github repo data, and then i store it in redis with set. with get am getting current data, but when i trying add function to get it's not working.
let redisClient;
(async () => {
redisClient = redis.createClient();
redisClient.on("error", (error) => console.error(`Error : ${error}`));
redisClient.on("connect", function () {
console.log("Redis Connected!");
});
await redisClient.connect();
})();
// Make request to Github for data
async function getRepos(req, res, next) {
try {
console.log("Fetching Data...");
const { username } = req.params;
// with this am getting result
const cacheResults = await redisClient.get(username);
console.log(cacheResults);
// with this am not getting result, how can i fix this?
redisClient.get(username, (err, data) => {
console.log(data);
});
const response = await fetch(`https://api.github.com/users/${username}`);
const data = await response.json();
const repos = data.public_repos;
// Set data to Redis
redisClient.set(username, JSON.stringify(repos));
res.send(setResponse(username, repos));
} catch (e) {
console.log(e);
res.status(500);
}
}
it's don't console.log(data), i searched a lot and everyone have one example how to use get function, but in me case it's don't log, whats am doing wrong?
this is my cache function
// Cache middleware
async function cache(req, res, next) {
const { username } = req.params;
try {
await redisClient.get(username).then((data) => {
if (data !== null) {
res.send(setResponse(username, data));
} else {
next();
}
});
} catch (error) {
console.log(error.toString());
}
}
app.get("/repos/:username", cache, getRepos);
it's works, but time finish times with cache and without it are same? am doing something wrong?
can you try like this
redisClient.get(username).then((data) => {
console.log(data);
});

Sending "data" in res.send(), gives error on front end

I want to send the data in res.send(data). When i
console.log("This dox data",text);
in terminal, it works fine. It logs all text content in terminal. But accessing at frontend it gives me error
router.get("/api/emailtemplates/data/:subject", (req, res) => {
Email_templates.find({subject: req.params.subject}, (err, data) => {
if (!err) {
const val = data[0]['template_file_link'];
console.log(val);
const data= textract.fromFileWithPath(val, function( error, text ) {
console.log("This dox data",text);
});
res.send(data);
} else {
console.log(err);
}
});
You were trying to return wrong thing you need to send response in callback of the textract function
router.get('/api/emailtemplates/data/:subject', async (req, res) => {
try {
const templates = await Email_templates.find({ subject: req.params.subject });
const val = templates[0].template_file_link;
console.log(val);
textract.fromFileWithPath(val, (error, text) => {
console.log('This dox data', text);
return res.json({ text });
});
} catch (error) {
console.log(error);
return res.status(500).json({ error: true });
}
});
That code will give you the error Uncaught ReferenceError: Cannot access 'data' before initialization. You're trying to use the data constant you've declared within the if (!err) block before that constant has been initialized, because you've used data both as the name of the parameter you're going to receive the data from Email_templates.find in and also as the constant you store the result of textract.fromFileWithPath in. Here's a simpler example of the problem:
function example(err, data) {
// ^^^^−−−−−−− parameter called `data`
if (!err) {
const val = data[0]['template_file_link'];
// ^^^^−−−−−−−−− ReferenceError here
// because this is trying to use
// the constant below before it's
// initialized (it's in the "Temporal
// Dead Zone")
const data = "whatever";
}
}
example(null, [{template_file_link: ""}]);
Use different names for them. For instance:
router.get("/api/emailtemplates/data/:subject", (req, res) => {
Email_templates.find({subject: req.params.subject}, (err, data) => {
if (!err) {
const val = data[0]['template_file_link'];
console.log(val);
const fileData = textract.fromFileWithPath(val, function( error, text ) {
// ^^^^^^^^
console.log("This dox data",text);
});
res.send(fileData);
// ^^^^^^^^
} else {
console.log(err);
}
});
});

error in getting the response, if nodejs server send response after some delay

I am trying to upload the image, and then nodeJS server send the path of that image folder back as a response.
But When I sending the response after performing some task, nothing happening on angular-side.
this is my component.ts file.
uploadImage() {
const formData = new FormData();
formData.append('photo', this.image);
const obj$ = this.userService.uploadData(formData);
obj$.subscribe(data => {
console.log(data); //// nothing happening.
if (data.success) {
this.uploadForm.patchValue({
document: data.url
});
}
});
}
and my service.ts
uploadData (uploadImage) {
return this.http.post<UploadPhoto>('/user/upload', uploadImage);
}
and my app.js
router.post('/upload' ,upload.single('photo'), (req,res) => {
console.log(req.file);
const body = req.file;
cloudinary.uploader.upload(body.path, (err, result) => {
if (err) {
console.log(err);
return;
}
console.log(result);
res.status(200).json({
url: result.url,
success: true
});
});
});
But when I am sending response without performing any task, it works fine like
router.post('/upload' ,upload.single('photo'), (req,res) => {
console.log(req.file);
const body = req.file;
res.status(200).json({
url: 'hello',
success: true
})
});
I don't know why is this happening.
Please someone help me.
When an error occurs in your uploader you're returning the error to the console and then ending execution. If there is an error in the asynchronous method you must pass it to the next() function so that express can handle it.
router.post('/upload' ,upload.single('photo'), (req,res, next) => {
console.log(req.file);
const body = req.file;
cloudinary.uploader.upload(body.path, (err, result) => {
if (err) {
console.log(err);
next(err);
}
else {
console.log(result);
res.status(200).json({ url: result.url, success: true });
}
});
});

Node.js: Async fs.writeFile queue is creating race condition?

I am trying to use async with node.js to handle multiple incoming POST requests to edit a JSON file. No matter how I refactor it, it will always make one of the edits and not the other. I though that using async.queue would force the operations to handle sequentially? What am I doing wrong?
My code:
var editHandler = function(task, done) {
var req = task.req;
var res = task.res;
fs.stat( "./app//public/json/" + "data.json", function(err, stat) {
if(err == null) {
console.log('File exists');
} else if(err.code == 'ENOENT') {
console.log("Error");
} else {
console.log('Some other error: ', err.code);
}
});
console.log(req.params.id);
console.log(req.body);
fs.readFile( "./app//public/json/" + "data.json", 'utf8', function (err, data) {
data = JSON.parse( data );
data[req.params.id] = req.body.school;
//console.log( data );
fs.writeFile("./app//public/json/" + "data.json", JSON.stringify(data), function (err){
if(err) {
return console.log(err);
}
})
res.redirect('/');
});
};
//Make a queue for the services
var serviceQ = async.queue(editHandler, 20);
serviceQ.drain = function() {
console.log('all services have been processed');
}
app.post('/edit_school/:id', function(req, res) {
serviceQ.push({req: req, res: res })
})
Thanks in advance for any insights! I am really new to using node.js for anything other than npm/webpack.

Using the results of a GET request in Express router

First Node/Express app.
I'm having a hard time wrapping my head around on how to retrieve data from an endpoint and rendering it in the browser.
I have a dataservice.js that gets a JSON object from an endpoint like this:
const http = require('http');
getFinhockeyData = function() {
http.get('http://tilastopalvelu.fi/ih/modules/mod_standings/helper/standings.php?statgroupid=3545', (res) => {
console.log(`Got response: ${res.statusCode}`);
var body = "";
res.on('data', function (chunk) {
body += chunk;
})
res.on('end', function () {
var data = JSON.parse(body);
console.log('data parsed.');
console.log('first team name: ' + data.teams[0].TeamName);
console.log(typeof data);
return data;
})
}).on('error', (e) => {
console.log(`Got error from Finhockey: ${e.message}`);
});
}
module.exports.getFinhockeyData = getFinhockeyData;
Up until now things work and the data object can be console.logged and its content is usable.
The router.js looks currently like this:
'use strict';
const express = require('express');
const async = require('async');
const router = express.Router();
const dataservice = require('./dataservice.js')
router.get('/', function(req, res) {
async.series([
function(callback) {
getFinhockeyData(callback)
}
],
function(err, results) {
console.log('start rendering');
res.render('index', { data: data });
})
});
module.exports = router;
When I run the app and refresh the / route, I can see from the console that the getFinhockeyData is called and the data object's content is available in dataservice.js's console.logs, but the browser window hangs and the res.render part is never reached.
I understand that the rendering should be done only after the endpoint data request has finished (async.series usage), but it seems that I lack a fundamental understanding on how to actually use the result data from the getFinhockeyData function in the main route.
Any advice on this? I'll be happy to provide more info if necessary.
Firstly, doing the request is asynchronous, so you'll have to use either a callback or a promise.
Even the async middleware won't let you just return data from an asynchronous call, it requires a callback, but using native promises seems easier here
const http = require('http');
getFinhockeyData = function() {
return new Promise( (resolve, reject) => {
http.get('http://tilastopalvelu.fi/ih/modules/mod_standings/helper/standings.php?statgroupid=3545', (res) => {
var body = "";
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
resolve( JSON.parse(body) );
});
}).on('error', reject);
});
}
module.exports.getFinhockeyData = getFinhockeyData;
Also note that you're exporting as a module with a property
module.exports.getFinhockeyData = getFinhockeyData;
when you're going to use that in the routes, you have to use the property
const dataservice = require('./dataservice.js');
router.get('/', function(req, res) {
dataservice.getFinhockeyData().then(function(data) {
res.render('index', { data: JSON.stringify(data) });
}).catch(function(err) {
// epic fail, handle error here
});
});
You are responding to your route call with
res.render('index', { data: data });
But there is no data variable. It should be
res.render('index', { data: results });
Which is the variable where you are storing your data when it comes from the callback
The reason for res.render() not being called is, http requests are async. To get the response a callback must be passed, which you did but forgot to call it in the dataservice.js
This should help...
Change your dataservice.js like the following...
const http = require('http');
getFinhockeyData = function(callback) {
http.get('http://tilastopalvelu.fi/ih/modules/mod_standings/helper/standings.php?statgroupid=3545', (res) => {
console.log(`Got response: ${res.statusCode}`);
var body = "";
res.on('data', function (chunk) {
body += chunk;
})
res.on('end', function () {
var data = JSON.parse(body);
console.log('data parsed.');
console.log('first team name: ' + data.teams[0].TeamName);
console.log(typeof data);
callback(null, data); //returning the data to the callback
})
}).on('error', (e) => {
console.log(`Got error from Finhockey: ${e.message}`);
callback(e, null);
});
}
module.exports.getFinhockeyData = getFinhockeyData;
Change your router.js like the following...
router.get('/', function(req, res) {
async.series([
function(callback) {
getFinhockeyData(callback)
}
],
function(err, results) {
if(err === null){
console.log('start rendering');
res.render('index', { data: results[0] });
}
})
});

Categories

Resources