Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catch asynchronous network error from XMLHttpRequest send()

I'm making an http request asynchronously using XMLHttpRequest:

xhr.open(method, uri, true);

When I send something:

xhr.send(something)

When the server is down, it throws the following error:

net::ERR_CONNECTION_REFUSED

How can I catch and handle this error? The standard try..catch block doesn't work as the request is asynchronous.

Thanks in advance.

like image 326
rustybeanstalk Avatar asked Aug 20 '14 00:08

rustybeanstalk


People also ask

What are the types of send () method used for XMLHttpRequest?

send() The XMLHttpRequest method send() sends the request to the server. If the request is asynchronous (which is the default), this method returns as soon as the request is sent and the result is delivered using events. If the request is synchronous, this method doesn't return until the response has arrived.


2 Answers

Use the onerror event of the XMLHttpRequest:

function aGet(url, cb) {
    var x = new XMLHttpRequest();
    x.onload = function(e) {
        cb(x.responseText)
    };
    x.onerror= function(e) {
        alert("Error fetching " + url);
    };
    x.open("GET", url, true);
    x.send();
}

var dmp = console.log.bind(console); // Dummy callback to dump to console
aGet("/", dmp) // Ok, uses onload to trigger callback
aGet("http://dgfgdf.com/sdfsdf", dmp); // Fails, uses onerror to trigger alert
like image 198
dandavis Avatar answered Sep 27 '22 19:09

dandavis


I wrote a full solution to that problem. It works perfectly!
I have a function called networkOrfail which will try to resend the XMLHttpRequest each second, if the network is available. Otherwise, it'll ignore the request.
When the request is succeeded, that polling stops and the response is returned.

Here's how to detect whether the network is available:

function getNavigatorConection() {
    return navigator.onLine;
}

Then, create your XMLHttpRequest:

function makeRequest() {
    let xhr = new XMLHttpRequest();
    xhr.open('GET', 'anypage/anotherpage', true);
    xhr.timeout = 2000;
    xhr.onload = function () {
        // Your request is completed
        if (xhr.readyState == 4 && xhr.status == 200) {
            // You're in a successfully condition
        }
    };
    xhr.ontimeout = function (e) {
        // Your request timed out
    };
    xhr.send(null);
}

Now, define your polling method as follows:

function networkOrFail(callFunc, callTime) {
    let connected = getNavigatorConection();
    let callableTimes = callTime < 2000 ? 2000 : callTime;
    let toursBegin = 3;
    let tours = toursBegin;
    let intervalId;
    let request = function() {
        intervalId = setInterval(function() { 
        let connected = getNavigatorConection();
        if (tours > 0) {
            if (connected) {
                callFunc();
                tours =0;
                return false;
            }
            tours--;
            alert("i tryied againt to resend for another time and it remain just "+tours+" to retry");
        } else {
            clearRequest();
            tours =toursBegin;
        }
    }, callableTimes > 5000 ? 5000 : callableTimes);

    };
    let clearRequest = function() {
        clearInterval(intervalId);
        intervalId = null;
    };
    if (connected)
        callFunc();
    else
        request();
}

Finally, call the send method through the polling method by passing it toghether with the timeout in minutes:

networkOrFail(makeRequest, 5000);
like image 23
Ir Calif Avatar answered Sep 27 '22 19:09

Ir Calif