javascript - 挂起的 ajax 获取期间页面重新加载

标签 javascript ajax wcf

我有一个 Web 服务,其方法需要相当长的时间才能完成。 所以我启动了ajax客户端。它发送请求并等待。 请求完成后一切都很好。

但是当我在浏览器(比如说 Chrome)中使用重新加载/刷新选项时,一切都崩溃了。 待处理的请求在新页面中显示为仍待处理。新的待处理请求已发出,但旧的请求仍保留在那里。 新请求滞后或停止响应。

服务器故障?不是真的,因为当我重新启动浏览器本身时一切正常。

顺便说一句,在最新的 Firefox 上,当我在 ajax 获取期间重新加载页面时,我的 ajax 应用程序崩溃了。我的意思是它卡在第一个ajax请求上。当然,重新启动浏览器会有所帮助。

配置如下: 我的服务是在本地主机上运行的 WCF 服务。该服务响应 GET 请求,但必须使用通过 cookie 发送的 API key 对它们进行身份验证。该服务主要返回 JSON 响应。

通信使用 CORS,没有问题。

我使用 MiniWeb 服务器测试我的客户端。该应用程序是纯 ECMAScript,没有框架或依赖项。

这是我的 ajaxGet 方法:

/**
 * Performs a GET request to the WCF, returns response data.
 * @param {any} path Request path without domain and service path.
 * @returns {object} Response data.
 */
async ajaxGet(path) {
    let isFirstCookieSet = false;
    if (this.serviceDomain === undefined) this.parseBaseUrl();
    Cookie.set({ "api-key": this.apiKey }, { "domain": this.serviceDomain, "path": this.servicePath });
    let response = null;
    try {
        response = await fetch(this.baseUrl + path, {
            "method": "get",
            "mode": "cors",
            "credentials": "include"
        });
    } catch (error) {
        console.info("Caught error during fetch operation before getting response body.");
        throw new BackendError(404, "Service not available");
    }
    if (response.status !== 200) throw new BackendError(response.status, response.statusText);
    let container = await response.json();
    let data;
    for (let k in container) if (container.hasOwnProperty(k)) {
        data = container[k];
        break;
    }
    Cookie.set({ "base-url": this.baseUrl, "api-key": this.apiKey }, { "expires": DateTime.now.addYears(1).value, "samedomain": true });
    return data;
}

嗯,这取决于我的其他代码(显然该方法是 App 类、DateTimeBackendError 类的一部分),但这与这里无关。

如何防止这种奇怪的、未定义的行为? 有没有特殊的fetch选项?我应该设置特定的请求 header 吗?我应该在我的 Web 服务中设置特定的响应 header 吗?还有其他魔法吗?

更新: 我发现我可以手动中止待处理的请求:

How do I cancel an HTTP fetch() request?

但是,如果我可以在浏览器重新加载时发送信号,那么它就会起作用,并且据我所知,当它发生时,无法执行任何脚本。或者说有可能吗?

最佳答案

长话短说:我们需要AbortControllerwindow.onbeforeunload

let abortController = new AbortController();
window.onbeforeunload = function(e) { abortController.abort(); };
let myResponse = await fetch(uri, { /* my other options */, "signal" : abortController.signal });

这里发生了什么?浏览器允许在请求页面刷新(或者可能关闭选项卡等)时执行一些清理操作。它位于 window.beforeunload 事件处理程序中。然后我的 fetch() 调用获取可选的 CancelationToken 对象,它是来 self 的 AbortController 实例的信号。当 Controller 被触发时,所有 token 都会收到中止信号并被取消。

MDN 说这个东西是实验性的。不管怎样,它在 Firefox、Chrome 和 Opera 上都能正常工作。

关于javascript - 挂起的 ajax 获取期间页面重新加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51471901/

相关文章:

Javascript - 表单选择元素在新窗口中打开 url 并提交表单

javascript - 如何解码二进制音频数据?

javascript - MEAN 堆栈卡在本地主机 :3000 上

java - 此 WSDL 是否缺少方法?

javascript - 如何在点击 react 时为唯一的一个元素切换类

javascript - 以发送它们的相同顺序显示 AJAX 响应,*不*使用排队或同步请求?

jquery - 处理跨域 jsonp 调用的 jQuery.ajax 错误

javascript - 将对象参数传递给 setInterval

java - Android 调用 AsyncTask 时崩溃

c# - 如何创建包含 CRL 分发点的自签名证书