Navigator.sendBeacon-页面关闭也能发送哀求

开发者 2024-9-21 12:29:10 70 0 来自 中国
配景

近来在需求中有一个如许的场景:必要在页面关闭的时间,用户不必要操纵,主动关闭当前订单
其时思量的方案:在页面关闭的时间,向后端发送一个哀求,将这个资源开释掉;
定下方案时,以为也不是什么难事,以为谷歌欣赏器应该会提供页面关闭的 API 供开发者使用。
颠末查找,找到了这么两个 API :beforeunload 和 unload
beforeunload

当欣赏器窗口关闭或者刷新时,会触发 beforeunload 变乱。当前页面不会直接关闭,可以点击确定按钮关闭或刷新,也可以取消关闭或刷新。
window.addEventListener('beforeunload', function (event) {  // Cancel the event as stated by the standard.  event.preventDefault();  // Chrome requires returnValue to be set.  event.returnValue = '';});该变乱会使网页在脱离或者刷新的时间弹出一个对话框,给用户一个提示。在这个弹框出现时,该页面是做不了任何操纵的,除非把这个弹框关闭。其他页面也只能举行简单的点击欣赏操纵,键盘是操纵不了的。
这个不符适用户无感知的条件
unload

当文档或一个子资源正在被卸载时, 触发 unload 变乱。
unload 变乱在 beforeunload 变乱后触发,这时间文档处于一个什么状态呢?
所有资源都存在,像图片,iframe的等,但是这些资源对于用户来说均不可见,界面上的交互也是无效的.
使用方式和 beforeunload 雷同,但是 unload 变乱中不能使用确认框,毕竟都已经在卸载了
window.addEventListener('unload', function(event) {  console.log('unload');});题目


  • 用户无论刷新照旧关闭了页面,由于这两种操纵都会调用beforeunload和 unload。
  • 异步哀求会被 cancel 掉,导致哀求无法发送乐成,由于使用的axios举行哀求,欣赏器有几率关闭异步哀求,造成哀求无法发出,可以实验换成同步。
    在变乱的回调中使用同步的 AJAX 哀求。
window.addEventListener('unload', function (event) {  let xhr = new XMLHttpRequest();  xhr.open('post', '/log', false);  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');  xhr.send('foo=bar');});但是谷歌欣赏器已经不答应页面关闭期间举行同步的 XMLHTTPRequest(),这条规则实用于 beforeunload、unload、pagehide和visibilitychange这些 API;
为了确保页面在卸载时讲数据发送到服务器,官方发起使用 sendBeacon()或者 Fetch keep-alive
Navigator.sendBeacon

这个方法告急用于满意统计和诊断代码的必要,这些代码通常实验在卸载(unload)文档之前向web服务器发送数据。
Beacon API 有以下如许几个特点:


  • 通过 HTTP POST 将少量数据异步传输,可靠性好
  • 这个哀求不必要相应,保证在页面的 unload 状态从发起到完成之前被发送。
  • 不会壅闭页面卸载,也就不会影响下一导航的载入
  • 支持跨域
  • 不支持自界说哀求头
    用法如下:
navigator.sendBeacon(url, data);url 就是上报地点,data 可以是 ArrayBufferView,Blob,DOMString 或 Formdata,根据官方规范,必要 request header 为 CORS-safelisted-request-header,在这里则必要保证 Content-Type 为以下三种之一:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain
我们一样平常会用到 DOMString , Blob 和 Formdata 这三种对象作为数据发送到后端,下面以这三种方式为例举行阐明。

  • DOMString
如果数据范例是 string,则可以直接上报,此时该哀求会主动设置哀求头的 Content-Type 为 text/plain。
const reportData = (url, data) => {  navigator.sendBeacon(url, data);};

  • Blob
如果用 Blob 发送数据,这时必要我们手动设置 Blob 的 MIME type,一样平常设置为 application/x-www-form-urlencoded。
const reportData = (url, data) => {  const blob = new Blob([JSON.stringify(data), {    type: 'application/x-www-form-urlencoded',  }]);  navigator.sendBeacon(url, blob);};

  • Formdata
可以直接创建一个新的 Formdata,此时该哀求会主动设置哀求头的 Content-Type 为 multipart/form-data。
const reportData = (url, data) => {  const formData = new FormData();  Object.keys(data).forEach((key) => {    let value = data[key];    if (typeof value !== 'string') {      // formData只能append string 或 Blob      value = JSON.stringify(value);    }    formData.append(key, value);  });  navigator.sendBeacon(url, formData);};注意这里的 JSON.stringify 操纵,服务端必要将数据举行 parse 才气得到精确的数据。
Fetch keep-alive

当使用fetch() 方法时,如果把keeplive 设置为true,即便页面被制止哀求也会保持毗连。
window.onunload = function() {  fetch('/analytics', {    method: 'POST',    body: "statistics",    keepalive: true  });};
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 16:48, Processed in 0.160626 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表