res.send not working properly - javascript

I am working with a simple CRUD app with jquery ajax and node.js, just to improve my skills with node and ajax. The thing is that I am doing a post request that is handled with my post router in the node server, and everything is working fine. It adds 1 more product to my products.json file, but in the end it doesn't send the response back to the client, the final res.send("done") doesn't work and I don't know why..
here is the code:
ajax
$("#create-form").on('submit',function(){
event.preventDefault();
var createIn = $("#create-input").val();
$.ajax({
url: '/products',
method:'POST',
data:JSON.stringify({name:createIn}),
contentType: "application/json",
dataType: "json",
success: function(data){
console.log(data);
$("create-input").val("");
$("get-button").click();
}
});
})
node
app.post('/products',function(req,res){
fs.readFile('products.json','utf8',function(err,data){
var result = JSON.parse(data);
var productName = req.body.name;
console.log(req.body.name);
currentId++;
var productId = currentId;
var product = {
name: productName,
id: productId
}
result.products.push(product);
fs.writeFile(__dirname + "/products.json",JSON.stringify(result),'utf8');
});
res.send("post done");
});
This is just the important part of the code, it works and just fails at the end in the res.send.

Your client code is looking for a json response, but you are returning a string.
$("#create-form").on('submit',function(){
event.preventDefault();
var createIn = $("#create-input").val();
$.ajax({
url: '/products',
method:'POST',
data:JSON.stringify({name:createIn}),
contentType: "application/json",
dataType: "json", <--------------
success: function(data){
console.log(data);
$("create-input").val("");
$("get-button").click();
}
});
})
Either delete this line or add on the server side
res.send({"message":"post done"});

This does not answer your question directly but you should ideally not send back the response until you know the work has been done, and you should handle errors. In other words you should use the callbacks. (Too many callbacks can be problematic and you should investigate other patterns - eg promises - bit no need here)
app.post('/products',function(req,res){
fs.readFile('products.json','utf8',function(err,data){
if (err) return res.send("error");
var result = JSON.parse(data);
var productName = req.body.name;
console.log(req.body.name);
currentId++;
var productId = currentId;
var product = {
name: productName,
id: productId
}
result.products.push(product);
fs.writeFile(__dirname + "/products.json",JSON.stringify(result),'utf8', function(err, res) {
if (err) return res.send("error");
res.send("post done");
});
});
});

Related

How to download data created server-side with Node.js?

I want to retrieve some data from my REST API in Node to the user directly downloaded in json file when he clicks a link.
I tried some stuff using Blop, but it is not working in my case I don't understand why...
HTML
<div class='wrapper_align_vertical'>
<a class='shortCut' id='extract'>Extract</a>
</div>
JS (sample that is working)
Viewed this example on internet and worked well with sample data.
document.getElementById('extract').onclick = function(event){
var data = { a: 1, b: "hello" }
var json = JSON.stringify(data)
var blob = new Blob([json], {type: "octet/stream"})
var url = window.URL.createObjectURL(blob)
this.href = url
this.target = '_blank'
// target filename
this.download = 'data.json'
}
But in my case I am calling API to gather data from database before creating the blop.
How I am getting data
I am calling the API with ajax request.
function getFromDB(){
return new Promise(function(resolve, reject){
$.ajax({
url: '/api/extract',
dataType: "json",
type: 'GET',
headers: {
"x-access-token" : getCookie('token')
},
success: function(data){
if(data.success == 'true'){
resolve(data)
} else{
reject('Promise getFromDB failed !')
}
}
})
})
}
EDIT : I added error verification in case the promise fail, and it is not the case unfortunately ! Moreover I printed the data in the console and everything seems fine, it is complete... Resolve data is sending back the right json object.
What return the route /api/extract
The route get data from DB.
router.get('/', function(req, res, next){
var query = 'SELECT ...'
connection.query(query, function(err, rows){
var result = []
if(!err){
for(label in rows){
result.push(rows[label].path)
}
res.json({
success: true,
data:{
quantity : rows.length,
image: result
}
})
}else{
res.json({
success: false,
message: 'Failure while extracting tags from database !'
})
}
})
})
What I want to do
But it is absolutely not working, maybe I am missing something ?
document.getElementById('extract').onclick = function(event){
getFromDB()
.then(function(data){
var json = JSON.stringify(data)
var blob = new Blob([json], {type: "octet/stream"})
var url = window.URL.createObjectURL(blob)
this.href = url
this.target = '_blank'
this.download = 'data.json'
}, function(err){
// Promise failed
console.log(err)
})
}
More informations
I saw something else that might help debugging... While using the API with Postman I am getting header 200 :
GET /api/extract 200 5.484 ms - 375
BUT ! When it's through the ajax call, I get code 304 :
GET /api/extract 304 6.339 ms - -
If you have any advice or suggestion I'll appreciate, thank you !

How to return database data in HTTP get method

In server side,I fetch data from database
var sql = require('mssql');
app.get('/api/comments', function(request, response) {
var sqlConfig = {
// Connection string parameters.
}
sql.connect(sqlConfig, function() {
var request = new sql.Request();
var stringRequest = 'select TOP 10 * from comment';
request.query(stringRequest, function(err, recordset) {
if(err) console.log(err);
sql.close();
response.json(recordset);
});
});
});
Then,I fetch the data from server side by AJAX (get method)
_fetchComments() {
jQuery.ajax({
method: 'GET',
url: '/api/comments',
success: (comments) => {
this.setState({ comments })
}
});
I get an error when I get the data by Ajax.
(Uncaught TypeError: this.state.comments.map is not a function)
It seems that the data return is undefined.Instead of fetching database,the code is work if I use static data(hard code) in server side.
I think the problem is the callback function in sql.connect() but I have no idea how to solve it.Does anyone can help?
Error:
The solution is adding dataType: 'json' to the ajax
_fetchComments() {
jQuery.ajax({
method: 'GET',
url: '/api/comments',
dataType: 'json',
success: (comments) => {
this.setState({ comments })
}
});
}

How to get data with ajax from a query string from a route in Node.js?

Like my title says, I am trying to pull data from a route with a AJAX Request that holds json data ('/home/playback/json'). But this data won't exist unless a query is done But I am trying to incorporate this from my client side page(playback.ejs) but I can't connect a query to my route that is connected to my database. Any ideas or documentations I should try out?
AJAX Request
$(document).ready(function () {
$('#search').on('submit', function() {
$.ajax({
url: "http://localhost:8080/home/playback/json",
contentType: "application/json",
dataType: 'json',
success: function (data) {
console.log(data);
},error: function () {
alert('error');
},
type: "GET",
});
});
});
Route.js
app.get('/home/playback', function (req, res) {
res.render('playback.ejs');
});
app.get('/home/playback/json', function (req, res) {
//database connection
dbconnection.query("SELECT * FROM myTable WHERE FILE_NUM LIKE '%" + req.query.searchFileNumber + "%' LIMIT 5", function (err, rows, fields) {
if (err) throw err; //Show any errors
var data = [];
for (i = 0; i < rows.length; i++) {
data.push(rows[i]);
}
res.json(data);
});
});
I might be missing something, but wouldn't this work?
$.ajax({
url: "http://localhost:8080/home/playback/json?searchFileNumber=1",
....
Also: watch out for SQL injection vulnerabilities. Without proper user input sanitation anyone could drop your database.

jQuery ajax calls with nodeJS

These are my code blocks.
API Endpoint
app.get('/clients/zvb/:id', function(req, res) {
console.log('ZVB Query loaded as var = file;')
var path = './public/queries/zvb.sql'
var zvb = fs.readFileSync(path, "utf8")
zvb = zvb.splice(25, 0, req.params.id)
request.query(zvb, function(err, recordset) {
console.log(recordset);
res.end(JSON.stringify(recordset));
});
})
Then my index.html where I try and GET the data from the endpoint.
$.ajax({
type: 'GET',
url: 'http://localhost:8081/clients/zvb/16601',
dataType: 'jsonp',
success: function(data) {
console.log(data);
console.log('we got to here..')
}
});
Not much is happening at the moment. When I try and manually run the ajax call in the terminal I get;
Object {readyState: 1}
The endpoint is working, if I view it I can see the JSON i'm after.
Tom
If you are using jquery 1.5+ these shorthand methods are very easy to use.
(I can't comment or would have asked). Doc is here http://api.jquery.com/category/ajax/shorthand-methods/
$.get( "http://localhost:8081/clients/zvb/16601", function(data) {
var data = JSON.parse(data);
})
.done(function() {
})
.fail(function() {
})
.always(function() {
});

AJAX requests to Node.JS to update JSON file for Jquery-comments

Jeez... How about that title, terrible lol.
Well I am using jquery-comments by Viima. (http://viima.github.io/jquery-comments/)
I'm trying to use ajax commands to a Node.JS script that will update a JSON file. All of which is local, no crossing domains or anything.
Here is my Node.JS script:
var http = require('http');
var fs = require('fs');
http.createServer(function (req, res) {
fs.writeFile("/comments-data.json", "commentJSON", function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
});
}).listen(8080, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8080/');
Here is the Ajax post
postComment: function(commentJSON, success, error) {
$.ajax({
type: 'post',
url: 'http://127.0.0.1:8080',
data: commentJSON,
success: function(comment) {
success(comment)
},
error: error
});
},
I don't want to redirect. I just wanted to asynchronously show the new comment. Also this script will ultimately have to be able to handle video attachments as well and store the filepath inside the JSON file. But i believe, Jquery-comments just reads the file path from the JSON
Here is what the support site says for attachments
uploadAttachments: function(commentArray, success, error) {
var responses = 0;
var successfulUploads = [];
var serverResponded = function() {
responses++;
// Check if all requests have finished
if(responses == commentArray.length) {
// Case: all failed
if(successfulUploads.length == 0) {
error();
// Case: some succeeded
} else {
success(successfulUploads)
}
}
}
$(commentArray).each(function(index, commentJSON) {
// Create form data
var formData = new FormData();
$(Object.keys(commentJSON)).each(function(index, key) {
var value = commentJSON[key];
if(value) formData.append(key, value);
});
$.ajax({
url: '/api/comments/',
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false,
success: function(commentJSON) {
successfulUploads.push(commentJSON);
serverResponded();
},
error: function(data) {
serverResponded();
},
});
});
}
});

Categories