背景

最近在需求中有一个这样的场景:

需要在页面关闭的时候,用户不需要操作,主动关闭当前订单

当时考虑的方案:在页面关闭的时候,向后端发送一个请求,将这个资源释放掉;

定下方案时,觉得也不是什么难事,觉得谷歌浏览器应该会提供页面关闭的 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

官方链接 https://developer.mozilla.org/zh-CN/docs/Web/API/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
  });
};

以上就是Navigator sendBeacon页面关闭也能发送请求方法示例的详细内容,更多关于Navigator sendBeacon请求发送的资料请关注Devmax其它相关文章!

Navigator sendBeacon页面关闭也能发送请求方法示例的更多相关文章

  1. react-native-tab-navigator组件的基本使用示例代码

    本篇文章主要介绍了react-native-tab-navigator组件的基本使用示例代码,具有一定的参考价值,有兴趣的可以了解一下

  2. Flutter Navigator路由传参的实现

    本文主要介绍了Flutter Navigator路由传参的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. js使用visibilitychange处理页面关闭事件

    本文主要介绍了js使用visibilitychange处理页面关闭事件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  4. JavaScript之BOM location对象+navigator对象+history 对象

    这篇文章主要介绍了JavaScript BOM中的 location对象、navigator对象、history 对象,下面围绕他们的相关语法及各种资料展开文章详细内容,需要的小伙伴可以参考一下,希望对大家有所帮助

  5. 详解Stack Navigator中使用自定义的Render Callback

    这篇文章主要为大家介绍了Stack Navigator中使用自定义的Render Callback使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  6. JavaScript中的Navigator浏览器对象

    JavaScript中的Navigator浏览器对象

  7. springboot vue测试平台接口定义及发送请求功能实现

    这篇文章主要为大家介绍了springboot+vue测试平台接口定义及发送请求功能实现,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  8. 微信小程序使用navigator实现页面跳转功能

    本周学习了navigtor到导航组件,目前我想使用navigtor组件实现跳转以及返回功能,下面这篇文章主要给大家介绍了关于微信小程序使用navigator实现页面跳转功能的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

  9. Navigator sendBeacon页面关闭也能发送请求方法示例

    这篇文章主要为大家介绍了Navigator sendBeacon页面关闭也能发送请求的方法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. React-Native中禁用Navigator手势返回的示例代码

    本篇文章主要介绍了React-Native中禁用Navigator手势返回的示例代码,具有一定的参考价值,有兴趣的可以了解一下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部