【问题标题】:Catch asynchronous network error from XMLHttpRequest send()从 XMLHttpRequest send() 捕获异步网络错误
【发布时间】:2021-01-01 17:37:04
【问题描述】:

我正在使用 XMLHttpRequest 异步发出 http 请求:

xhr.open(method, uri, true);

当我发送something:

xhr.send(something)

当服务器宕机时,会抛出如下错误:

net::ERR_CONNECTION_REFUSED

如何捕捉和处理这个错误?标准的try..catch 块不起作用,因为请求是异步的。

提前致谢。

【问题讨论】:

标签: javascript html http xmlhttprequest


【解决方案1】:

使用XMLHttpRequestonerror事件:

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

【讨论】:

  • 我的印象是只有 Chrome、Safari 和 Firefox 支持,Opera 或各种移动浏览器不支持。你知道onerror的支持是什么吗?谢谢。
  • 看起来相当不错:caniuse.com/#feat=xhr2,加上msdn.microsoft.com/en-us/library/ie/cc288060(v=vs.85).aspx,你必须将两者合二为一才能达到 95%,但这对你来说是香草!
  • 这对我不起作用。我正在尝试发出 PUT 请求,当服务器返回错误时,xhr.onerror 或 xhr.upload.error 处理程序都没有捕获错误。将错误传播到浏览器会导致其他 javascript 问题。
  • 仍然在控制台中抛出一个令人讨厌的错误。有什么办法可以防止吗?
【解决方案2】:

我为这个问题写了一个完整的解决方案。效果很好!
我有一个名为networkOrfail 的函数,如果网络可用,它将尝试每秒重新发送XMLHttpRequest。否则,它将忽略该请求。
当请求成功时,轮询停止并返回响应。

以下是检测网络是否可用的方法:

function getNavigatorConection() {
    return navigator.onLine;
}

然后,创建您的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);
}

现在,如下定义您的轮询方法:

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();
}

最后,通过轮询方法调用发送方法,将超时时间与分钟一起传递:

networkOrFail(makeRequest, 5000);

【讨论】:

    猜你喜欢
    • 2022-11-03
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多