页面关闭前发送请求

906 阅读2分钟

背景

一个需求,希望用户在离开页面的时候,向后端发起一个请求,告诉后端:“我走了”。由此,后端可以在该用户的信息中标记一个“走了”的标志。

环境

  • chrome

前置知识

选择方案

使用navigator.sendBeacon发送异步请求

MDN是这样介绍的:

navigator.sendBeacon()  方法可用于通过 HTTP POST 将少量数据异步传输到 Web 服务器。

它主要用于将统计数据发送到 Web 服务器,同时避免了用传统技术(如:XMLHttpRequest)发送分析数据的一些问题。

MDN上有详细的使用说明,这里就不赘述了;需要注意的是该方法ie不兼容;

image.png

尝试方案

1. unload事件添加ajax接口请求

  1. 直接在unload事件添加ajax方法(同步)与后端交互。

image.png

上图可以看到,当ajax使用的是同步的方法,刷新过后,unload里面的 get 方法并没有被触发。

  1. 直接在unload事件添加ajax方法(同步)并且使用for循环进行延时与后端交互。

结果与方案1一样

  1. 直接在unload事件添加ajax方法(异步)与后端交互。

image.png

上图中可以看到,使用同步的方式,在刷新页面的时候,后台有机会接收到请求。

  1. 直接在unload事件添加ajax方法(异步)并且使用for循环进行延时与后端交互
    get("a=beforeUnload");

    window.addEventListener('unload', function() {
        get("xhr=InUnload");
        for (let i = 0; i < 30000; i++) {
        	
        }
    })

    function get(str) {
        //创建xhr对象
        var xhr;
        if (window.XMLHttpRequest) {
            xhr = new XMLHttpRequest();
        } else {
            xhr = new ActiveXObject('Microsoft.XMLHTTP');
        }
        //发送请求
        xhr.open('get', `http://127.0.0.1:8631?${str}`, true);
        xhr.send();
        //同步接受响应
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                //实际操作
            }
        }
    }

image.png

可以看到请求可以稳定的成功发送给后台。但是看页面请求记录发现是cancel的状态,所以需要后台忽略abort,才能算请求成功

优点:兼容性好

缺点:不稳定,使用for循环阻塞页面刷新,用户体验不好,并且会固定等到for循环的时间;如果网络环境特别差,也是有可能失败的;如果网络环境特别好又浪费等待时间

参考