添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

如果开发者希望在 document 完成 unload 前向服务器发送数据,通常不能直接发起 asynchronous XMLHttpRequest
unload 事件响应的回调函数中,这里因为浏览器会 abort 这样的请求。

通常为了实现这样的需求,有以下几种方式可供选择:

  • synchronous XMLHttpRequest
  • 既然浏览器会 abort asynchronous XMLHttpRequest ,那我们可以考虑发起 synchronous XMLHttpRequest 请求,在
    unload 或者 beforeunload 时间的回调函数中,这样的同步请求会阻塞住 document unload 的进程,直到请求的数据发送完成。

    1
    2
    3
    4
    5
    6
    7
    8
    window.addEventListener('unload', sendData, false);

    function sendData() {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "/collect_data", false); // third parameter indicates sync xhr
    xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
    xhr.send('test');
    }

    效果如下:

  • fake img element
  • 实现上述需求,也可以通过在 unload 或者 beforeunload 时间的回调函数中创建一个 img element ,并将数据通过指定图片 src 的方式将数据发送到后端。这是因为大多数浏览器会延迟 document unload 进程直到完成所有未完成加载的图片完成加载。

    1
    2
    3
    4
    5
    6
    7
    window.addEventListener('unload', sendData, false);

    function sendData() {
    var img = document.createElement('img');
    img.src = 'http://example.com/collect_data.jpg?data=test'
    document.body.append(img);
    }

    效果如下:

  • navigator.sendBeacon
  • 前两种方式,都存在着一个问题:由于阻塞了 document unload 进程,这样就会影响到下一个页面的加载(相关数据收集 API 出现性能问题 or 网络时延)。

    navigator.sendBeacon 的出现,正好解决了这个问题。其定义如下:

    1
    can be used to asynchronously transfer a small amount of data over HTTP to a web server.(可以异步地通过 `HTTP` 向服务端发送小数量的数据。)

    navigator.sendBeacon 的调用,并不是直接将数据发给后端,而是将待发送的数据放入浏览器待传输队列,浏览器再将待传输的数据发送到
    后端,这样就不会阻塞 document unload 进程,用户也不会长时间等待。

    1
    2
    3
    4
    5
    window.addEventListener('unload', sendData, false);

    function sendData() {
    navigator.sendBeacon('/collect_data', 'test');
    }

    效果如下:

    PS: 这里虽然 chrome network 面板显示请求处于 pending 状态,但是请求已经发送到了后端,只是还未得到响应,作者没有深入探究,猜测和在 unload 回调中执行有关。

  • https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
  • https://github.com/fatelei/unload_send_data
  •