【问题标题】:Delay Return to Wait for Asynchronous Functions (beforeunload event)延迟返回等待异步函数(beforeunload 事件)
【发布时间】:2016-10-29 16:09:07
【问题描述】:

在这个编码示例中,函数logout() 不会执行所有它的异步调用,也不会等到它们完成——而是在之前卸载页面,因为beforeunload 事件的返回触发了页面卸载。

$(window).on('beforeunload', function(event) {
    event.preventDefault();
    logout();
    return;
});

我想尝试的是事件函数在logout()中的几个异步调用完成后返回。

编辑:我的目标是显示警报!我只想在页面卸载之前执行一些代码。注销功能可能包含需要完成的 ajax 请求和 jQuery 动画。

我尝试了回调,但最终得到了这个结果,因为它返回的是回调,而不是事件函数,所以不是想要的结果。

$(window).on('beforeunload', function(event) {
    event.preventDefault();
    logout(function(x) { return; });
});

【问题讨论】:

  • @E.Mourits 不,你读过我的问题吗?它与离开和导航的区别无关,而是在页面卸载/新页面加载之前执行代码。
  • 据我所知,您无法阻止用户离开您的页面。可能的重复是我认为最接近您想要的答案。
  • @E.Mourits:我可以。 beforeunload 函数在之前执行。如果其中有一段时间(真),则用户不能离开。我看不出您的参考与我的问题有关。
  • 好吧..你可以,但你真的不应该。当他/她试图离开时,你为什么要让他/她离开?向您的页面添加注销按钮也可以。

标签: javascript jquery asynchronous google-chrome-extension jquery-events


【解决方案1】:

由于页面卸载时页面上执行的所有内容都将变为无效,因此您不能依赖页面本身来完成异步调用。

chrome 扩展 的一个解决方法是使用背景页面。您可以简单地将消息发送到beforeunload 处理程序内的后台页面,捕获您需要处理的所有信息,并在后台页面中执行异步调用。示例代码是:

content.js

window.addEventListener('beforeunload', function() {
    chrome.runtime.sendMessage({ info: "Here is the info you would like to pass to background page"});
});

background.js

chrome.runtime.onMessage.addListener(function(request) {
    // The following is your async call
    logout();
    // Don't forget the following code
    return true;
});

不要忘记在后台页面的事件监听器中返回true,因为当事件监听器返回时chrome.runtime.onMessage.addListener会失效,更多细节见this answer

【讨论】:

  • 这对于后端任务来说是个好主意。但是我可以从后台脚本中显示一些东西吗,也许使用 chrome.tabs.executeScript - 但我认为它也会被刷新并且不会停留多久我希望它停留?
【解决方案2】:

尝试为您的处理程序使用async/await,即:

$(window).on('beforeunload', async function(event) {
    await logout();
    event.preventDefault();
    event.returnValue = false; // Seems require this for Chrome
});

当然,你应该从logout()返回Promise

但我不确定这是否可靠。

【讨论】:

  • 将事件处理程序标记为异步实际上在 Chrome 中可靠地工作。非常好。
  • 这不起作用。 async 函数返回一个 Promise,如果调用 ($(window).on...) 没有等待,它会在 promise 解决之前继续,并且在 await logout() 完成之前卸载页面。 async/await 不会使异步调用同步。它只是 Promises 的语法糖。
【解决方案3】:

不是一个真正干净的解决方案,但您可以尝试 setTimeout 强制代码在注销过程中等待。

var timeToLogoutInMs = 500;
setTimeout(function() {
    // Nothing
}, timeToLogoutInMs);

编辑:为什么需要在 beforeunload 挂钩上执行此操作?为什么不设置手动选项用户退出?

【讨论】:

  • 据我所知 setTimeout 是异步执行的,这意味着它将立即继续下一条语句(返回)。注销只是一个例子——实际上它是关于谷歌浏览器扩展的。我在页面中注入了一些代码,并希望在页面卸载之前显示一些内容。
  • 这不会改变行为。
  • 嗯,我明白了。如果你在同一个钩子中调用 alert 会发生什么?弹出的警报会暂停卸载吗?
  • @tetutato 你说得对,警报是同步的,但你不能在其中放置警报:„[...] window.showModalDialog(), window.alert() 、window.confirm() 和 window.prompt() 方法在此事件期间可能会被忽略。” - 但是例如 while(true) 会阻止它卸载。
猜你喜欢
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-26
  • 2013-07-24
  • 2020-12-23
  • 1970-01-01
相关资源
最近更新 更多