在卸载事件之前有什么限制?

Wal*_*ril 10 javascript browser

beforeunload回调中有什么和不可能做什么?

是否可以打开XHR/fetch并将数据发送到服务器?如果不是,是否可以只发送数据,而没有任何成功的回调阻止?

是否可以更改页面的位置window.location?功能继续执行多长时间?

window.addEventListener("beforeunload", function (event) {
    // code
});
Run Code Online (Sandbox Code Playgroud)

fny*_*fny 26

您可以在"beforeunload"回调中放置任何您想要的内容,除非您使用同步/阻塞代码,否则您无法保证它会执行.

这是一个阻塞睡眠功能,我将用于演示目的:

function sleep(delay) {
  var start = new Date().getTime();
  while (new Date().getTime() < start + delay);
}
Run Code Online (Sandbox Code Playgroud)

任何同步阻塞代码都保证执行完成:

window.addEventListener("beforeunload", function (event) {
  console.log("Blocking for 1 second...");
  sleep(1000);
  console.log("Done!!");
});
Run Code Online (Sandbox Code Playgroud)

任何异步代码(即带有回调的代码)都会在事件循环中排队,但它可能会也可能不会完成执行,具体取决于浏览器何时完成"卸载"操作(例如关闭窗口,刷新页面).这里的时间真的取决于你的电脑的性能.例如,在我的计算机上,由于我的浏览器没有时间刷新/关闭页面,因此执行日志语句的超时时间为10毫秒.

window.addEventListener("beforeunload", function (event) {
  setTimeout(() => {
    console.log("Timeout finished!"); // Odds are this will finish
  }, 10);
  console.log("Done!!");
});
Run Code Online (Sandbox Code Playgroud)

但是,永远不会执行100ms的超时:

window.addEventListener("beforeunload", function (event) {
  setTimeout(() => {
    console.log("Timeout finished!");
  }, 100);
  console.log("Done!!");
});
Run Code Online (Sandbox Code Playgroud)

保证函数运行完成的唯一方法是确保编写阻塞事件循环的同步代码,如第一个示例所示.

  • @RyanWheale这个的主要用例是检测用户何时填写表单但未提交表单,或者在没有保存的情况下完成其他操作,我们正在尝试提供帮助. (4认同)
  • 所以在你的第一个例子中,如果我想编写保证运行的代码,我会把它放在哪里?我看到您创建了一个睡眠函数来阻止事件循环,但是哪个 console.log 可以保证运行?您会将保证完成的内容放在哪里,例如提交 GET 请求? (3认同)
  • 问题,添加 `while(!asyncCompleted);` 拦截器会起作用吗? (2认同)
  • 没有。while 循环将阻止异步事件完成,因此您将陷入无限循环。 (2认同)

Ant*_*ony 9

为了帮助第一个答案的评论中的一些人,请查看此功能以在卸载事件期间发出 XHR 请求:https : //developer.mozilla.org/en-US/docs/Web/API/Navigator/发送信标