Ajax请求有时失败 - 有和没有jQuery

时间:2015-12-12 22:56:58

标签: javascript jquery ajax

简介

这个问题似乎比实际更长,但我试图保持一个干净的结构。

首先,我有这个webapp,它需要在文件大小非常小才能在智能手机上完全加载(没有缓存)< 10秒。这要求我不要使用像jQuery这样的库(无论如何都不重要,见下文)。

没有jQuery

我基本上使用MDN Ajax page来创建这个简短的包装器:

function ajax(options) {
    var request;

    if (window.XMLHttpRequest) {
        request = new XMLHttpRequest();
    } else {
        request = new ActiveXObject("Microsoft.XMLHTTP");
    }

    request.timeout = 6500;
    request.ontimeout = function () {
        // not called, 6.5s is too high for a timeout anyway, checked this one first
        options.error(request);
    };

    request.onreadystatechange = function () {
        if (request.readyState == 4) {
            if (request.status >= 200 && request.status < 400) {
                options.success(request.responseText);
            } else {
                options.error(request);
            }
        }
    };

    request.open("GET", options.url, true);
    request.send();
}

然而,有时(在1/15到1/100的情况下)请求失败。我得到一个类似于这个的请求对象:

XMLHttpRequest { 
    onreadystatechange: ajax/request.onreadystatechange(), 
    readyState: 4, 
    timeout: 6500, 
    withCredentials: false, 
    upload: XMLHttpRequestUpload, 
    responseURL: "my-url", 
    status: 0, // <-- this seems to be the main problem
    statusText: "",
    responseType: "",
    response: "" 
}

要指出这一点,我不是在这里尝试做CORS,而是在同一个域上。此外,超时设置为6.5秒,如果我查看其他请求,它们通常在~45ms内完成。我试图&#34;重试&#34; Ajax 3x如果失败了一次,就会抓住&#34; status = 0&#34; -problem,但是这仍然没有成功,因为它仍然存在,0意味着网络服务器没有交付任何内容(这种解决方法似乎只是一个非常脏的黑客)。

使用jQuery Ajax

在我使用jQuery的另一个项目中,因为我没有这些大小限制。我正在使用常规的jQuery.ajax调用,就像这样:

$.ajax({
    url: url,
    dataType: "json",
    success: options.updateSuccess,
    error: options.updateError,
    timeout: options.updateTimeout
});

然而,即使这个有时也失败,statusCode = 0(updateTimeout设置为65s,因为我可以等待这个&#34;)。此外,它与第一个代码段不同,是一个不同的网络服务器。

到目前为止我尝试了什么?

  • 做一些研究(原来很多人都想使用我不想做的CORS)
  • 阻止浏览器使用网址的缓存版本,方法是在网址上添加时间戳("&cache=" + new Date().getTime(),也不起作用)
  • 检查网络服务器是否有错误的配置(它不是这个问题的根源,我甚至尝试使用简短的Python脚本在Ajax调用的相同间隔内轮询网站,它们都成功了)
  • 尝试了不同的浏览器:这主要发生在Firefox中,虽然Chrome似乎偶尔也会失败

最终问题

为什么会这样呢?我不能反复复制它,它有时会发生。这是一个浏览器错误,使每个第n个Ajax调用失败吗?你有什么不同的方法来解决这个问题(最好用简单的Javascript)吗?

更新

我做了更多的研究,这次是使用wireshark。我记录了哪个请求导致status = 0,然后查看了这些包的TCP流程图,所有请求都得到了服务器的答案,我想这不是服务器端问题。

1 个答案:

答案 0 :(得分:3)

所以我通过做了很多测试来解决这两个问题。 jQuery一个很简单,更新到jQuery 2.1.4解决了它,我不想知道导致这个的原因,它现在只是工作

对于第二个问题,我将超时时间减少到500毫秒,然后遇到超时,导致我被onreadystate调用,即使请求没有完成(在及时得到答案方面)因此得到status = 0。为什么会发生这种情况,见上文。确保超时不仅仅是&#34;随机&#34;我添加了一个重试计数器并修改了我的Ajax函数:

function ajax(options) {
    var request;

    if (options.retry === undefined) {
        options.retry = 3; // modify here for default retry count
    }

    if (window.XMLHttpRequest) {
        request = new XMLHttpRequest();
    } else {
        request = new ActiveXObject("Microsoft.XMLHTTP");
    }

    request.timeout = options.timeout ? options.timeout : 500; // modify here for default timeout
    request.ontimeout = function () {
        if (options.retry > 0) {
            options.retry--;
            ajax(options);
        } else {
            options.error(request);
        }
    };

    request.onreadystatechange = function () {
        var delta = new Date().getTime() - request.startTime;

        if (request.readyState == 4) {
            if (request.status >= 200 && request.status < 400) {
                options.success(request.responseText);
            } else if (request.status === 0 && delta >= request.timeout) {
                // do nothing as this was "just a timeout"
            } else {
                options.error(request);
            }
        }
    };

    request.startTime = new Date().getTime();
    request.open("GET", options.url, true);
    request.send();
}