4

So I'm using plain javascript (no jquery), to send a file to the server. Server script PHP returns status code 200 at the end, but instead javascript is getting readyState == 2.

The PHP code sends back status code 200:

header('X-PHP-Response-Code: 200', true, 200);
exit;

The javascript is doing:

request.onreadystatechange = function() {
        if (request.readyState == 4) {
            var message;
            switch(request.status) {
                case '200':
                     message = "Data uploaded successfully.";
                break;

                case '406':
                    message = "Incorrect file format.  Please try again.";
                break;

                case '410':
                    message = "Unexpected error.  Please contact support.";
                break;

                default:
                break;
            }
            status_message_container.innerHTML = message;
            submit_button.disabled = false;
        }
        else {
            alert( "Unexpected error:  " + this.statusText + ".\nPlease try again");
        }
    };

    request.send(formData);

Even know the HTTP 200 status code comes back correctly (I get 'OK') on frontend. The JS script is seeing readyState==2 (i.e. else block always hit)

My understanding is that a server status code of 200 should give readyState == 4??

snowbound
  • 1,692
  • 2
  • 21
  • 29

1 Answers1

10

Firstly, onreadystate isn't just fired once. It's fired multiple times, you need to be able to handle that. These are the codes you need to handle:

0 UNSENT - open()has not been called yet
1 OPENED - send()has not been called yet
2 HEADERS_RECEIVED - send() has been called, and headers and status are available
3 LOADING Downloading; - responseText holds partial data
4 - The operation is complete

Your code is hitting the else block on readyState == 2 (headers received) and assuming that is an error status when it's not.

You error check should be inside the request.readyState == 4 check. That way, the request is complete but there could also have been an error:

if (request.readyState == 4) {
    switch(request.status) {
        case '200':
            message = "Data uploaded successfully.";
        break;
        // Error handling here
        default: alert( "Unexpected error:  " + this.statusText + ".\nPlease try again"); break;
    }
}

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest

CodingIntrigue
  • 75,930
  • 30
  • 170
  • 176
  • I realise `onreadystate` hits multiple times - anytime readyState changes in fact. Specifically I'm wondering why **readyState isn't 4** when I sent back HTTP 200? Isn't the operation **completed** by then? If not, what indicator does the server script have to give to get `readyState == 4`? _EDIT:_ Your code will fail because readyState == 2 on HTTP status 200. – snowbound Oct 17 '14 at 07:29
  • Your readyState probably did hit the completed block, eventually. It's just that it'll hit the "error" part first when it receives the error. It should always receive a *done* when a response is received - whether or not it's an error is defined by its response code. Updated answer to better explain that – CodingIntrigue Oct 17 '14 at 07:31
  • My code won't fail. readyState is *both* 2 (when the headers are received) **and** 4 (when the response has been downloaded) when *any* status code is returned. – CodingIntrigue Oct 17 '14 at 07:33
  • Is there any readystate will tell request is sent out successfully from OPENED? if readysate 2 means HEADERS_RECEIVED, means it got the response header already? – Nasir Jun 08 '23 at 04:04