I am having a problem with node.js where every time I run a query, it reruns all the previous queries ran, along with the new one.
More specifically: I have a form with three fields: first name, last name, email. When I submit that form, I want to: - check if the user already exists in the database (I do this with a SQL query on the email address). - if client exists, display a message on the form that the client can't be added. - if the user DOESN't exists, add the client to the database and display a 'Successfully added client' message on the form.
Seems easy, right?
What is happening is that for the first new user I add, everything is fine. Then I add a second new user, but what happens in the database is that it adds TWO entries: it re-adds the first new user, and the second as well. If I try to add a third user, it ends up running 3 'INSERT INTO' queries, adding the first user (a third time) and the second user again, then the third. And so on...
It's like there is some storage somewhere that I am not clearing out between form submissions - but I'm not using a session here, so I don't know where this form data is being persisted!
Any thoughts? I am very new to node.js and I think I must be missing something very fundamental, but I can't see it.
Here is the javascript and form from my 'index.html' file:
<script type="text/javascript">
$(document).ready(function(){
$("#new_client").submit(function(){
var form = $(this);
//remove previous message section
form.siblings('p').remove();
$.getJSON(
form.attr('action'),
form.serialize(),
function (result){
if (result.success == true){
$(form).before("<p>Success: "+result.message+"</p>");
}
else if (result.success == false){
var html = "";
for (var i = 0; i < result.message.length; i++){
html += "<p>Failed: "+result.message[i]+"</p>";
}
$(form).before(html);
}
}); //end $.getJSON
return false;
});
});
</script>
<body>
<form id="new_client" action="/add_client" method="get">
<!-- NOTE: we need to use method="get" for getJSON -->
<input type="text" name="first_name" placeholder="Client first name">
<input type="text" name="last_name" placeholder="Client last name">
<input type="text" name="email" placeholder="Client email">
<button type="submit">Add Client</button>
</form>
</body>
And here are parts of my nodejs code (server.js):
var http = require('http');
var url = require('url');
var path = require('path');
var fs = require('fs');
var querystring = require('querystring');
var mysql = require('mysql');
var events = require('events');
var Validator = require('validator').Validator;
var eventEmitter = new events.EventEmitter();
var db = mysql.createConnection({
//host:'localhost',
port: 8889,
user: 'root',
password: 'root',
database: 'test_database'
});
server = http.createServer(function (request, response){
var pageUrl = url.parse(request.url).pathname;
if(pageUrl === '/add_client'){
var dataQuery = url.parse(request.url).query;
var formData = querystring.parse(dataQuery);
//set up event listener for 'add client result'
eventEmitter.on('addClientResult', function (result){
response.end(JSON.stringify(result));
});
//set up listener for existing client check
eventEmitter.on('clientIsNewResult', function (result){
if (result.success === false){
response.end(JSON.stringify(result));
}
else {
//this will trigger the 'addClientResult' event
addClient(db, formData.first_name, formData.last_name, formData.email);
}
});
//set up event listener for validated data
eventEmitter.on('validateDataResult', function (result){
if (result.success === false)
response.end(JSON.stringify(result));
else{
//trigger 'clientIsNewResult' event
clientIsNew(db, formData.email);
}
});
// trigger the validateDataResult event
validateData(formData.first_name, formData.last_name, formData.email);
} //end 'add_client'
else { ... code for other actions and where we start the response object... }
}); //end of server object
server.listen(8080);
function clientIsNew(db, email){
db.query('SELECT * FROM clients WHERE email=?', [email],
function (errors, results, fields) {
if (errors) throw errors;
//console.log(this.sql);
if (results.length > 0){
query_result = {
'success': false,
'message': ['There is already a client with this email address!']
}
}
else {
query_result = {
'success': true,
'message': 'This is a unique user'
};
}
eventEmitter.emit('clientIsNewResult', query_result);
});
}
function addClient(db, first_name, last_name, email){
//the only time we should get here is when we want to create a new user
//so we should only get here when 'clientIsNewResult' is triggered and gets
// a result of true... at least that is the intention!
db.query('INSERT INTO clients SET first_name=?, last_name=?, email=?, created_at=NOW();',
[first_name, last_name, email],
function (errors, results, fields) {
if (errors) throw errors;
//console.log(this.sql);
insert_result = {
'success': true,
'message': 'Client is added'
}
eventEmitter.emit('addClientResult', insert_result);
}
);
}
function validateData(first_name, last_name, email){
... validates info, no problems with this ...
eventEmitter.emit('validateDataResult', result);
}
console.log('Server running at http://localhost:8080/');
OK, I hope that wasn't too much, I deleted a lot of comments and other console.log lines I had in there as well.
Please let me know if I need to post more, or less, or if I've forgotten something.
Thanks in advance for your help!
Move you Event emitter to inside you http request
move
var eventEmitter = new events.EventEmitter();
to
server = http.createServer(function (request, response){
var pageUrl = url.parse(request.url).pathname;
var eventEmitter = new events.EventEmitter();
Finally got some guidance from a mentor. My problem is that every time I send data to the server, I am creating another event listener, but the previous event listener(s) still exist. So the second time I submitted the form, there were two event listeners on the same event; the third time, there were three... ect.
Solution: major refactor of code, to not use so many. ALSO: changing eventEmitter.on() to eventEmitter.once() for the addClientResult event, which is the only event listener left. After all, I only want to add a client once each time I submit data to the server.