Jacob Windsor
Jacob Windsor

Reputation: 6990

xhr error status of 0 but script proceeds regardless

I have an asynchronous audio upload script that works perfectly but there is one issue that is bugging me. The only thing it messes up is the error handling as an error is handled with an xhr status of 0 but there is seemingly no error as the upload continues.

xhr.upload.addEventListener("progress", keepPage(file,xhr),false);
xhr.upload.addEventListener("progress", uploadProgress,false);
xhr.upload.addEventListener("load", uploadComplete, false);
xhr.upload.addEventListener("error", uploadFailed(xhr.status), false);
xhr.upload.addEventListener("abort", uploadCanceled, false);
xhr.open("POST", "http://" + document.domain + "/script.php", true);
xhr.send(fd);
var uploading = true;
uploaded = false;
xhr.onreadystatechange=function(){
    if (xhr.readyState==4 && xhr.status==200) {
        var response = xhr.responseText;
        if (response == "success"){
            var uploaded = true;
            processSuccess();
        }
        else {
            var obj = $.parseJSON(response); //parse error JSON array
            errReport = obj.errReport
            uploadFailed(errReport);
        }
     }
}
uploading_tools(file, xhr, uploaded);

The error event is fired as soon as the script starts uploading. I have put console.log(xhr.status) in the uploadFailed function and a status of 0 is fired.

I understand an xhr status of 0 is given when an ajax is called across domains but as you can see this is not the case.

If I cannot get rid of this annoying bug I will just have to ignore an xhr status of 0 in my error handling which is something I would like to avoid doing.

Edit:

xhr.open("POST", "http://" + document.domain + "/script.php", true);
xhr.upload.addEventListener("progress", keepPage(file,xhr),false);
xhr.upload.addEventListener("progress", uploadProgress,false);
xhr.upload.addEventListener("load", uploadComplete, false);
xhr.upload.addEventListener("error", uploadFailed(xhr.status), false);
xhr.upload.addEventListener("abort", uploadCanceled, false);
xhr.send(fd);
var uploading = true;
uploaded = false;
xhr.onreadystatechange=function(){
    if (xhr.readyState==4 && xhr.status==200) {
        var response = xhr.responseText;
        if (response == "success"){
            var uploaded = true;
            processSuccess();
        }
        else {
            var obj = $.parseJSON(response); //parse error JSON array
            errReport = obj.errReport
            uploadFailed(errReport);
        }
     }
}
uploading_tools(file, xhr, uploaded);

Upvotes: 1

Views: 881

Answers (1)

Oscar Paz
Oscar Paz

Reputation: 18312

Always call open() before accessing any other property or calling any other method of XMLHttpRequest. Strange behaviour can occur otherwise.

EDIt I just saw the light, you are not getting an error! You have this line:

xhr.upload.addEventListener("error", uploadFailed(xhr.status), false);

You aren't assigning uploadFailed() as the event handler for the error event. You are calling uploadFailed(xhr.status), so you are assigning as the event handler the return value of the function! Of course, surely uploadFailed does not return anything, so in the end you don't have an error handler. But, of course, when this line is executed your function is called! And as the call to xhr.send() hasn't occured yet, xhr.status is 0.

You have to change the line to

xhr.upload.addEventListener("error", uploadFailed, false);

Just like you have the others:

xhr.upload.addEventListener("progress", uploadProgress,false);
xhr.upload.addEventListener("load", uploadComplete, false);

NEW EDIT

In response to your comment, it doesn't work because you're doing the same you were doing, and not what I told you to do. Let's see if I can explain it to you.

Suppose your uploadFailed function is like this:

function uploadFailed(error) {
    console.log(error);
    return true;     //you won't have this line, but let's assume you do.
}

Now, you have this code:

xhr.upload.addEventListener('error', uploadFailed(errReport), false);

Well, what is this line doing? Exactly this:

var f = uploadFailed(errReport);   //uploadFailed is being called, not assigned to f
xhr.upload.addEventListener('error', f, false); //f is not a function, but the value 'true'!

Do you get it? When that line is executed, you are calling your function and assigning the result, not assigning the function itself. If your problem is how to pass the error value to the error function, you can do it this way:

function uploadFailed() {
    console.log(this); //when you assign this function as an event handler, 
                       //'this' will be the object which fired the event (xhr.upload)
}

You don't need to pass the xhr object to the function, but if, for whichever reason you need to pass the error as an argument, then you've got to do this:

xhr.upload.addEventListener('error', function() { uploadFailed(xhr.status); }, false);

This way you are defining a new function that has your xhr object in its scope and can pass it to your error function.

I hope you get the difference between a function and a function call, because it is essential.

Upvotes: 1

Related Questions