2
\$\begingroup\$

Today I created my first simple AJAX application. It works fine, but I am a bit unsure if I did everything correct. I'd like to use the code as template for future projects.

function _solve(id) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        var DONE = 4; // readyState 4 means the request is done.
        var OK = 200; // status 200 is a successful return.
        if (xhr.readyState === DONE) {
            if (xhr.status === OK) {
                obj = JSON.parse(xhr.responseText);
                if (obj.success) {
                    if (document.getElementById('line'+obj.id).style.display != 'none') {
                        document.getElementById('line'+obj.id).style.display = 'none';
                        document.getElementById('count').innerHTML = document.getElementById('count').innerHTML - 1;
                    }
                } else {
                    alert('Json error: ' + obj.error);
                }
            } else {
                alert('Error: ' + xhr.status); // An error occurred during the request.
            }
        }
    };
    xhr.open('POST', 'ajax_cmd.php', true);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.send('cmd=solve&id='+id);
}

Beside general improvement suggestions, I have following particular questions:

  1. Do I need to somehow close the connection? It looks like send() automatically closes the connection because I cannot execute send() twice.

  2. Is the error handling ok? When my internet connection was a bit unstable, I got the message "Error: 0". Zero sounds like a strange status code.

Note: For now, I'd like to stick with plain JavaScript, without jQuery or other frameworks.

Explanation/context of the code:

The HTML page has a table. Each table row  represents a dataset with an ID. The id of each row is "line" plus the dataset ID, e.g. "line1". Each table row has a link named "Solve" which calls the JavaScript function _solve(id).

<tr id="line61087">
  <td>php/error.log</td>
  <td><a href="javascript:_solve(61087)">Solve</a></td>
  <td>1113</td>
  <td>2017-09-03&nbsp;01:18:18</td>
  <td>Xyz...</td>
</tr>

When the user clicks at "Solve", a PHP script (ajax_cmd.php) is called with AJAX. The PHP script deletes the dataset and confirms the deletion with the JSON object success: true; id: (the ID) on success or success: false; error: (the error message) on failure.

After the PHP script confirmed the successful deletion, the AJAX script hides the table row and decreases a row counter.

A double-click prevention (which might result in a double-decrease of the counter) is realized with a check if the row is already hidden.

\$\endgroup\$
2
\$\begingroup\$

Let's start off with your questions:

Do I need to somehow close the connection? It looks like send() automatically closes the connection because I cannot execute send() twice.

No. The browser abstracts all connection details from you, like connection persistence, caching, protocols, etc. You just have to think that an instance of XMLHttpRequest represents one request-response pair.

Is the error handling ok? When my internet connection was a bit unstable, I got the message "Error: 0". Zero sounds like a strange status code.

A zero status code is a non-HTTP status code for a generic network failure. You can get that status code from invalid certificate errors, cross-domain errors, extensions blocking the connection, etc. On JS, you often cannot get any specific information from the error, and the only thing you can do is show a generic error message on your app. However, the browser console will tell you what happened exactly.

var xhr = new XMLHttpRequest();

Is so 2010. There's a simpler fetch that does more with a simpler syntax. Consider using that instead. It's inspired greatly by jQuery. If you're familiar with jQuery, you pretty much know what to do.

    var DONE = 4; // readyState 4 means the request is done.
    var OK = 200; // status 200 is a successful return.
    if (xhr.readyState === DONE) {
        if (xhr.status === OK) {

Unless you're reusing DONE and OK elsewhere, it's pointless to put them in variables. If one sees xhr code done manually, it's pretty much standard to check readyState 4 and status 200 when expecting a success.

obj = JSON.parse(xhr.responseText);

JSON.parse can throw an error when the string is malformed JSON. And malformed JSON can be caused by bad server code, or a misconfigured server that returns HTML error pages on errors. Wrap this in a try-catch, and fail the operation if it does throw.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.