前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >刷新/关闭页面之前发送请求

刷新/关闭页面之前发送请求

作者头像
OBKoro1
发布2020-10-27 14:24:09
3.6K0
发布2020-10-27 14:24:09
举报
文章被收录于专栏:OBKoro1的前端分享

本文中提到的链接,因为微信的限制,没有显示出来,查看文中链接,需要点击最下方的阅读原文链接

背景:

有一个任务非常耗时会消耗后台大量算力,所以在退出页面的时候,要求前端这边发送一个请求来杀死任务。

一开始以为这个需求非常简单,就是在进入其他路由前,发送一下请求,杀死 一下任务就好了。

然而现实狠狠的打了我的脸,因为退出页面的场景不止切换路由~

退出页面场景:

  1. 还在本网站,跳到其他路由
  2. 刷新页面/关闭页面

还在本网站,跳到其他路由

这个比较简单,在 Vue中可以通过路由离开的钩子 beforeRouteLeave来实现:

代码语言:javascript
复制
beforeRouteLeave(to, from, next) {
    if (任务运行中) {
        // 发送请求
    }else{
        next(true) // 用户离开
    }
 }

刷新页面/关闭页面的情况:

然而在刷新页面的时候, beforeRouteLeave并不会执行,接着想到了下面这两个 API.

beforeunloadunload

beforeunload 当浏览器窗口关闭或者刷新时触发:

介绍

使用这个 API可以阻止页面直接关闭,用户通过点击确定/取消按钮,来决定是否不关闭/刷新当前页面。

在 chrome 下长这个样子,你们肯定都见过:

如何使用

这个 API 的使用非常简单,只要在页面加载的时候监听一下此事件,在需要出现弹窗的时候return 一个可以转化为 true 的值,就可以了。

代码语言:javascript
复制
// 页面卸载之前
let killTask = false; // 是否杀死任务
window.onbeforeunload = e => {
  if (任务运行 && 对应页面) {
    killTask = true;
    return '您可能有数据没有保存'; // 在部分浏览器可以修改弹窗标题
  } else {
    killTask = false;
  }
  // 没有return一个可以转化为true的值 就不会出现弹窗
};

出现此弹窗的浏览器行为

以下行为是基于 chorme:

  1. 焦点:你没有点击取消/确定之前,焦点会一直在此弹窗上
  2. 你无法在出现弹窗的页面上执行任何操作
  3. 在其他页面也只能执行简单的点击操作,弹窗还是存在页面中间,无法使用键盘,
  4. 键盘:键盘被绑定在弹窗上,只能通过按键 EscEnter来执行取消/确定操作
  5. 弹窗不是页面的 dom,是浏览器的行为
  6. 用户取消/确定,没有回调 API,无法得知

弹窗标题

chrome 中刷新页面的标题: 重新加载此网站?

chrome 中关闭页面的标题: 离开此网站?

现在大部分浏览器都不允许修改弹窗的标题,这个是为了安全考虑,来保证用户不受到错误信息的误导,

迷茫

一开始我以为既然可以拦截到用户的刷新/关闭页面的操作,出现了上面那个弹窗,这个需求就已经做完了的时候。

然后发现,浏览器竟然没有提供用户点击确定/取消刷新页面的回调。

到这里我陷入了迷茫,盯着 beforeunload这个 API 思考了起了人生的意义(其实是在发呆),盯着盯着,从 beforeunloadbefore我也就想到了 unload这个 API。

瞬间又燃起了斗志,何不试试这个 unload

unload当页面正在被卸载的时候触发该事件

介绍

当页面正在被卸载的时候触发该事件,该事件不可取消,为不可逆操作。

使用

直接监听该事件就可以了。

代码语言:javascript
复制
window.onunload = e => {}

结合需求:

killTaskbeforeunload时定义的变量,每次进入回调,都会给 killTask赋值,使用这个值就可以判断什么时候可以发送请求杀死任务。

代码语言:javascript
复制
window.onunload = e => {
  if (killTask && 对应页面) {
    // 发送请求
  }
};

到这里大家肯定以为已经做出来了该需求,事实上,并没有!

无法发送异步请求

我使用的是 axios来发送请求,请求发出去了,但是被取消了,服务器那边根本没有收到请求,如下。

经过一顿分析:发现是 axios请求是异步的问题,谷歌之后发现axios不支持同步的请求

最后使用原生的XMLHttpRequest对象,让请求同步

大功告成!

小结:

在这两个API中,还有些事项需要注意:

  1. alert/ confirm/ debugger/ window.open等都无法使用
  2. 抛出错误无法终止这两个API
  3. 谨慎使用异步

以上2019.1.13

博客、前端积累文档、公众号、GitHub

以上,希望本文能够对你有一些帮助。

种一颗树最好的时间是十年前,其次就是现在了!

点击下方,阅读原文,访问文中链接吧!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-01-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OBKoro1前端进阶积累 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景:
  • 退出页面场景:
  • 还在本网站,跳到其他路由
  • beforeunload和 unload
    • beforeunload 当浏览器窗口关闭或者刷新时触发:
      • unload当页面正在被卸载的时候触发该事件
      • 小结:
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档