vue3 监听浏览器窗口关闭事件,该如何实现在窗口close前发送请求记录日志,并确保后台请求一定能执行完成?

vue3 监听浏览器窗口关闭事件,在窗口close前发送一个请求记录下使用记录这样子。
但是实际使用过程中发现有时候调请求存记录会不成功,并不是每次在使用完关闭窗口后都成功的存了使用记录。
请问是由于请求完成前浏览器已经关闭了导致请求取消造成的嘛?如果是的话,该如何确保在窗口关闭前,发送后台请求,且确保能请求执行完成呢?

代码如下:

//监听 浏览器窗口关闭事件,触发日志上传
onMounted(() => {
    window.addEventListener("beforeunload", (e) => beforeunloadHandler(e));
    window.addEventListener("unload", (e) => unloadHandler(e));

});
onUnmounted(() => {
    window.removeEventListener("beforeunload", (e) => beforeunloadHandler(e));
    window.addEventListener("unload", (e) => unloadHandler(e));
});

const beforeunloadHandler = async (event: any) => {
    if (state.totalPressCount > 0) {
        logEndTime.value = dayjs().format('YYYY-MM-DD HH:mm:ss');//add2023-07-25 plq
        // await submitAlarmCaseToolLog();
    }

    //网页上 显示确认对话框
    // Cancel the event as stated by the standard.
    // event.preventDefault(); // 取消默认的关闭操作
    // Chrome requires returnValue to be set.
    // event.returnValue = ""; // Chrome要求设置返回值才能触发提示框
}
const unloadHandler = async (event: any) => {
    if (state.totalPressCount > 0) {
        // logEndTime.value = dayjs().format('YYYY-MM-DD HH:mm:ss');//add2023-07-25 plq
        await submitAlarmCaseToolLog();
    }
}

//添加事件工具使用记录 add2023-07-25 plq
const submitAlarmCaseToolLog = async () => {
    const _requestData = {
        alarmCaseId: alarmCase_store.alarmCaseData?.id as number,
        toolKitId: guidanceToolsIdEnum.cpr_guide_tool,
        openTime: logStartTime.value,
        closeTime: logEndTime.value,
        resultId: "",
        resultName: `累计按压计数:${state.totalPressCount}`,
        assessFlowId: paramAssessFlowId.value,//问题关联工具 add2023-07-27 plq
        orderId: paramAssessOrderId.value,
        guidanceStepId: paramStepId.value, //指导步骤关联工具
        guidanceStepSourceId: paramStepSourceId.value,
    };
    let _res = (await addAlarmCaseToolLog(_requestData)).data;
    // console.log(_res);
};
阅读 3.2k
avatarAI BotBETA

从你的代码中看,你已经在窗口关闭事件中添加了请求记录日志的操作,但你遇到的问题是请求并不总是能成功执行。这是因为浏览器的安全策略不允许在窗口或标签页即将关闭时执行某些网络请求。

对于这种情况,一种可能的解决方案是使用fetch API 或 axios 这样的库来发送请求,并在请求的 promise 中使用 catch 来处理可能出现的错误。这样,即使请求因为浏览器的原因被取消,你也能捕获到错误并处理。

下面是一个使用 axios 的例子:

const submitAlarmCaseToolLog = async () => {
    try {
        const _requestData = {
            alarmCaseId: alarmCase_store.alarmCaseData?.id as number,
            toolKitId: guidanceToolsIdEnum.cpr_guide_tool,
            openTime: logStartTime.value,
            closeTime: logEndTime.value,
            resultId: "",
            resultName: `累计按压计数:${state.totalPressCount}`,
            assessFlowId: paramAssessFlowId.value,//问题关联工具 add2023-07-27 plq
            orderId: paramAssessOrderId.value,
            guidanceStepId: paramStepId.value, //指导步骤关联工具
            guidanceStepSourceId: paramStepSourceId.value,
        };
        let _res = (await axios.post('/your-api-endpoint', _requestData)).data;
        // console.log(_res);
    } catch (error) {
        console.error('Failed to submit log:', error);
    }
};

这样,如果请求因为浏览器的原因被取消,catch 块将会捕获到错误,并打印出错误信息。你可以根据需要进一步处理这个错误,例如重新发送请求或者给用户显示一个错误消息。

3 个回答
  window.addEventListener('beforeunload', () => {
    let blob = new Blob([JSON.stringify(params)], {
      type: 'application/json',
    });
    navigator.sendBeacon(window.location.origin+'请求路径',blob);
  })
  window.addEventListener("unload", () => { //部分手机可以获取到
 
    let blob = new Blob([JSON.stringify(params)], {
      type: 'application/json',
    });

    navigator.sendBeacon(window.location.origin+'请求路径',blob);
  })
  window.addEventListener("pagehide", () => {
    clearInterval(timer)
    let blob = new Blob([JSON.stringify(params)], {
      type: 'application/json',
    });
    localStorage.setItem('pagehide','pagehide')
    navigator.sendBeacon(window.location.origin+'请求路径',blob);
  },false);
  document.addEventListener("visibilitychange", () => {
    clearInterval(timer)
    let blob = new Blob([JSON.stringify(params)], {
      type: 'application/json',
    });
    localStorage.setItem('visibilitychange','visibilitychange')
    navigator.sendBeacon(window.location.origin+'请求路径',blob);
  })
  window.addEventListener("visibilitychange", () => {

    let blob = new Blob([JSON.stringify(params)], {
      type: 'application/json',
    });
    localStorage.setItem('winvisibilitychange','visibilitychange')
    navigator.sendBeacon(window.location.origin+'请求路径',blob);
  })
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏