Reputation: 14988
Here is a server-side function that receives a POST request and handles its response. As you can see, when no error occurs, the status code of the response is 200.
app.post('/submit', function(req, res) {
var p = new Promise(function(resolve, reject) {
db.serialize(function() {
db.run("INSERT INTO users VALUES (?, ?, ?, ?)",
[req.query['email'], req.query['company'], req.query['subject'], req.query['text']],
function (err) {
if (err) {
console.error(err);
reject();
} else {
console.log("Transaction passed");
resolve();
}
});
});
});
p.then(function(){
res.status(200).end();
}).catch(function() {
res.status(400).end();
})
});
In the client side, I wrote a JS function that sends an AJAX POST request to the server and handles the response:
function addFormToDB(email, company, subject, text) {
var xhttp = new XMLHttpRequest();
var params = "email=" + email + "&company=" + company + "&subject=" + subject + "&text=" + text;
xhttp.open("POST", "http://127.0.0.1:3000/submit?" + params, true);
xhttp.onreadystatechange = function() {
console.log(xhttp.readyState + " " + xhttp.status);
if (xhttp.readyState == 4 && xhttp.status == 200) {
console.log("request " + params + " was sent to DB");
alert("Thank You!");
}
};
xhttp.send();
}
When I invoke the function 'addFormToDB' from the console window of the browser, it sends an AJAX request to the server and gets it back with an xhhr.status of 200.
However, 'addFormToDB' has to be invoked when the user fills a form and clicks the 'submit' button. When this happens, the xhhr.status sent back from the server to the browser is always 0. I don't know why.
Here is the HTML code that creates the form:
<form id="form">
<label for="email"> E-mail: </label>
<input id = "email"> <br>
<label for="company"> Company: </label>
<input id = "company"> <br>
<label for="subject"> Subject: </label>
<input id = "subject"> <br>
<label for="text"> Text: </label>
<input id = "text"> <br>
<input type="submit" value="Submit" id="button"><br><br>
</form>
...
<script>
$("#form").submit(function() {
addFormToDB($("#email").val(), $("#company").val(), $("#subject").val(), $("#text").val())
});
</script>
Can you help me find out the bug?
Upvotes: 0
Views: 1362
Reputation: 338148
The immediate issue is that you don't prevent the default action of a form submit - which is to POST data to the server and reload the page. As a side-effect this cancels all running Ajax requests, which causes the effect you see.
To prevent the default event action, call preventDefault()
on the event object.
function submitHandler(e) {
e.preventDefault();
// some processing, for example Ajax
// the browser will not issue a traditional POST request
}
Back in the day, return false;
had the same effect, but nowadays.preventDefault()
is the way to go.
Further comments on your code:
Don't roll your own Ajax functions. Ajax libraries are plenty and convenient, well-tested and provide easy-to-read Ajax support that prevents common errors and does all kinds of heavy lifting transparently. Just use one of the many libraries.
With jQuery, which you seem to be using anyway, the function becomes as straight-forward as this:
function addFormToDB(email, company, subject, text) {
return $.post("http://127.0.0.1:3000/submit", {
email: email,
company: company,
subject: subject,
text: text
})
.done(function (data) {
console.log("received", data);
alert("Thank You!");
})
.fail(function (jqXhr, status, err) {
console.error(err);
});
}
Don't do your own promisification. It might look easy enough, but just as with Ajax, there's enough stuff that can go wrong and is easily overlooked. Let a library do it for you, or use a wrapper library that did it for you. For node-sqlite3, one such wrapper library exists: co-sqlite3. I recommend you look at it.
Your code could look like this:
app.post('/submit', function(req, res) {
var q = req.query;
var params = [q.email, q.company, q.subject, q.text];
db.serialize()
.then(() => db.run("INSERT INTO users VALUES (?, ?, ?, ?)", params))
.then(() => res.status(200).end())
.catch((err) => {
console.error(err);
res.status(400).end();
});
});
});
Or use one of the async/yield variants shown in the library's samples.
Upvotes: 1