Each ajax request is going to have overhead associated with it. It would be a bad idea to make a call for each row because it could overload the server with requests and you could DoS yourself if your receive enough traffic. Also, all browsers have a limit on how many HTTP requests can be made at once, so (depending on the browser), the deletions will happen in bursts, not all at once, even if you tell them to execute one after another.
Your best option would be to group the rows to edit/delete into a JSON array and send them to the server in a single request. On the server you can then parse the JSON and delete the items accordingly. Once you're finished, return a JSON array containing your results.
This jQuery pseudo-code code assumes you're either targeting browsers with a native JSON object, or you're using json2.js. Basically, this code just looks for "the hidden ID" field in each row of the table you display to the user and adds it to an array. You can adjust this as you feel it is needed.
var recordsToDelete = [];
$("tr.myRow").each(function() {
var id = $(this).find("input:hidden").val();
recordsToDelete.push(id);
});
var json = JSON.stringify(recordsToDelete);
Dealing with results can be harder. You should design your system so that (if successful), every row is deleted. Unless you're dealing with a very complex system, you should never have a situation where some rows pass and some rows fail. If this happens you need to re-consider your system architecture. jQuery has events for success
and failure
which you can use to deal with the general success or failure of the request, which I recommend you use.
Continuing from the code above, this is one way to deal with deleting records. I use the complete
event here for simplicity's sake, but you should use the success
and failure
events if possible. The complete
event always happens, whether a request succeeds or fails.
$.ajax({
url: "http://stackoverflow.com/questions/1653127",
type: "POST", // Always use POST when deleting data
data: { ids: json },
complete: function(xhr, status) {
var response = JSON.parse(xhr.responseXML);
// Response will be an array of key/value
// pairs indicating which rows succeeded or failed
for (var i = 0; i < response.length; i++) {
var recordID = response[i].recordID;
var status = response[i].status;
// Do stuff with the status codes here
}
}
});
In Response to Comments:
- For apps like gmail, the way it works is so massively complicated that saying "I'll do it this way because Google does it this way", isn't a good idea. Not everything that works for Google will work for every company or web site. Companies like Google have problems to deal with that almost no other web site needs to worry about. However to answer your question
- I just verified this to be sure: GMail uses one AJAX request with an array of IDs. No individual status codes are sent back. It seems like (and I'm speculating here) Gmail returns an "action ID" for the action you just performed, so you can undo that action by clicking an undo link that appears briefly after you delete an email.
- When working on an app, you generally want to make it reliable enough that operations don't fail. You should be performing rigorous QA to make sure of this. Basically, a delete operation should either pass or fail as a whole. A scenario where this could happen is if the user clicks delete as your server goes down. To the user, the site is still up because you're not reloading the page, but the AJAX request will fail because it has no where to go. You'll want to handle stuff like this.
- It really depends on the business rules of your app. If your application is being used in a situation where multiple people can change records at the same time (just an example), something that one user tries to delete could have been deleted by someone else just before they click that "delete" button. In most cases, I can't see people caring who deleted the record first since if it's deleted, it's deleted, no matter who really did it. However, a business rule may dictate (as ridiculous as it may be) that you need to report this information to the user. In this case you would have to return the array of statuses for every deletion.
- For preventing hackers from deleting other people's records, there are a few things to do:
- Treat your AJAX handlers no differently than the rest of the site. They should get no special privileges. A request to an AJAX handler should get authenticated just as everything else.
- Use POST requests (as I mention in my example) for destructive operations, or for operations that change data. This will make it harder for hackers to perform Cross-Site Request Forgeries (CSRF). Obviously this is not a foolproof thing to do, but it stops the easy exploits.
- Obviously, don't assume the user has the right to delete a record just because the user sent the deletion request. Make sure you verify that the user performing the deletion has the right to remove each record. How you do this will depend on your server-side application.
- Make sure you encode all of your values sent from the client to the server. This will prevent SQL injections.
- Make sure you're familiar with the OWASP Top Ten list. It covers the most common (but not all) major exploits on web sites and explains how to prevent becoming a victim of them.