当用户点击链接但取消时如何检测

4
我正在开发一个Web CMS。当用户点击链接进入不同的页面或提交表单时,我想让一个“请稍等”动画GIF出现在右上角以表示正在加载中。
但是,用户可以取消浏览器中新页面的加载,例如通过按下“取消”按钮或ESC键。在这种情况下,他们将停留在当前页面,因为浏览器停止加载下一个页面。
我该如何在Javascript中检测到这一点,并隐藏“等待”图标?
编辑:为了解决“你不应该这样做,浏览器已经有了”的评论。我有两个特定原因引入自定义解决方案。
1.页面上有AJAX按钮。我需要一个活动指示器,以便用户不会困惑于是否已注册单击。
2.在连接速度慢且延迟很高的情况下,某些浏览器的进度条会移动得非常缓慢。在IE6 / 7中,直到脉冲器显示任何类型的活动都需要很长时间。这给人一种没有任何事情发生并且应用程序反应非常缓慢的印象,这让我感到烦恼。我希望有一个不断移动的指示器(例如Safari的指示器)。

我总是觉得那些“等待”和“加载”很烦人。浏览器默认有它(在FireFox / Safari中是旋转器,在IE中是进度条)。最好考虑不要添加它? - user142019
2
在慢速系统和连接上,特别是IE在传达当前正在执行的操作方面非常模糊。出现一个快速弹出的符号可以解决这个问题。 - Pekka
1
关于 AJAX 的问题,如果你使用 jQuery,那么有一些全局事件处理程序可以很好地完成工作。请参见我在 jsfiddle.net/e4z9bv6k 上玩耍的一个小例子,以及一些非常有用的 Stack Overflow 帖子 stackoverflow.com/q/3735877、stackoverflow.com/q/9043768 和 stackoverflow.com/q/3709597。 - Adriano
即使在2014年,仍然存在现实工作情况,页面加载需要很长时间,并且在某些浏览器(例如Chrome)中,页面加载时只显示一个小的加载图标。我认为添加跨浏览器自定义样式是合理的。 - Adriano
6个回答

3
抱歉,我认为没有任何方法可以做到这一点。虽然你可以检测到按下了取消键,但是没有通用的方法来检测下一页的加载是否被取消。除非你猜测提交/点击后若干秒后仍在页面上,则可能已被取消或者你的服务器很慢。或者在同一页中使用AJAX进行整个导航和提交过程,这样可以通过打破浏览器自己的停止按钮来避免这个问题;但这可能不是一个好主意。(我认为添加自己的等待指示器也不是一个好主意;浏览器有一个完美的等待指示器!)

我同意,破坏停止按钮是不好的。嗯,如果这不能完成,那将太糟糕了。至于throbber,请参见我在上面问题中的编辑。 - Pekka
当进度条变慢时,是因为你正在进行一个大型表单提交吗?如果是这样的话,将其拆分为一个带有自己的加载动画的AJAX表单提交,然后再进行快速导航应该不难。 - bobince

1

(是的,我喜欢旧话题)

我在这里面临着同样的情况。我正在构建一些页面,其中导航是通过表单提交完成的,并且我发现在用户激动并触发15次相同的请求之前,向用户清楚地显示某些事情正在发生是很方便的 - “我们不信任用户,对吧?”

因此,我使用jQuery和一个名为Impromptu的不错的插件,可以在http://trentrichardson.com/Impromptu/index.php中找到。

以下是代码片段:

$(document).ready( function () {

 $("form").submit( function() {
  $.prompt( "<center>Sending request...</center>", {
   overlayspeed: 200,
   buttons:{}
  });

  setTimeout( "jQuery.prompt.close()", 2000 );
 });

});

Pekka正在寻找一种通用解决方案,以便在浏览器上检测“取消”操作。 - Adriano

1

这对提交按钮无效。一旦用户点击“提交”,请求就已经被发送到服务器。一旦发生这种情况,操作就已经完成了。在这种情况下,你能做的最好的事情就是阻止用户看到他们操作的响应,但是操作仍然会被执行。

此外,唯一阻止用户在另一个请求开始后导航到另一个页面的方法是将用户重定向回他们来自的页面。一般来说,取消请求只是一个纯粹的坏主意™。

对于表单,另一个选择是对所有表单提交使用AJAX。 AJAX请求可以被取消,因此你可以利用这一点,尽管这会使事情变得更加复杂和难以处理。

如果您仍然想继续,尽管知道其影响,您可以使用JavaScript框架(如jQuery、YUI、Dojo、MooTools、ExtJS或Closure)轻松实现此操作

以下是在jQuery中执行此操作的示例。正如我所提到的,一旦请求开始,您就无法停止它而不刷新用户所在的页面(以停止当前页面加载),因此我已从此示例中省略了该部分。

$().ready(function() { 
    function showLoading(){  
        $loadingOverlay = $('<div id="loadingOverlay"></div>'); 
        $loadingAnimation = $('<div id="loadingAnimation">Loading...</div>'); 
        $("body").prepend($loadingAnimation).prepend($loadingOverlay); 
    } 

    $("a[href]").click(showLoading); 
    $("form").submit(showLoading); 
});

要在加载框中添加一个动画 gif,请使用指向您选择的加载 gif 的 <img /> 标记替换文本 "Loading..."。这里可以查看此功能的实时演示:http://jsbin.com/opadi

您需要将此 CSS 与上述代码一起使用:

#loadingOverlay {
    position: absolute; 
    top: 0px; 
    left: 0px; 
    height: 100%; 
    width: 100%; 
    z-index: 1000; 
    background: #000;
    filter:alpha(opacity=50);
    -moz-opacity:0.5;
    -khtml-opacity: 0.5;    
    opacity: 0.5;
}
#loadingAnimation {
    position: absolute; 
    top: 30%; 
    left: 50%;
    z-index: 1001;
}

1
我的重点不是行动是否已执行 - 这由用户负责。 如果操作已被取消且未发生页面更改,则只需正确隐藏符号即可。 我正在寻找可以挂钩或可靠解决方法的事件。 - Pekka
从可用性的角度来看,那听起来像是一个糟糕的想法。你永远不应该有一个“取消按钮”,它实际上并没有取消任何东西。你所做的实际上只是创建了一个没有功能的取消按钮,除了隐藏取消按钮之外,却没有取消用户期望取消的操作。 - Dan Herbert
1
不,你没有理解,我想检测用户是否使用浏览器内置的取消按钮或按下Esc键取消加载下一页。用户的工作流程不会受到影响。 - Pekka
1
但是感谢丹提供了如此详尽的示例。在复杂系统中,从提交和/或导航切换到AJAX将产生太多影响,因此这对我来说不是一个选项。我已经澄清了我的问题,以突出我并不试图通过编程方式取消请求。 - Pekka

1

我认为你应该检查所谓的“锚点导航”。这里有一个很好的教程:

http://yensdesign.com/2008/11/creating-ajax-websites-based-on-anchor-navigation/

基本上,你会将用户引导到相同的URL,但在末尾加上锚点(http://localhost/home#somepage?param1=val1),然后使用AJAX加载数据。Javascript会捕捉锚点的变化,并可以显示“加载中”图标,并提供额外的功能,比如“取消加载”。在这种情况下,你的浏览器历史记录会保留,所以你可以在浏览器中点击“返回”,或者在Javascript中使用history.go(-1)来返回上一页。

1
转换为AJAX提交并不是一个真正的选择,因为它是一个复杂的系统,太麻烦了。但还是谢谢你的建议。 - Pekka
如果你想要实现那个功能,无论如何都必须使用JavaScript。而且,我相信这不会是每个页面都需要的,所以应该不难实现。不像GMail,它使用了锚点导航 :) 实际上,你可以尝试以下操作:打开GMail,在关闭网络连接后在"Inbox"和"Sent"之间切换 - 你会发现显示的是"页面未加载",而不是404错误! - Vitaly
如Pekka所指出的那样,锚点导航意味着从常规表单提交(由浏览器处理)切换到AJAX表单提交(由您编程处理)。是的,Gmail和其他单页应用程序通过程序化地进行一些客户端路由来完成一些酷炫功能,但如果您不是首次构建单页应用程序,则可能不是您想要做的事情。请参见http://read.humanjavascript.com/ch09-clientside-routing.html。 - Adriano
请注意,Pekka正在寻找一种通用解决方案,因此需要适用于他整个网站的解决方案... - Adriano

0

看起来window.onabort是一个很有前途的解决方案,但目前(2020年5月2日),它被标记为实验性技术,仅受Chrome和Edge支持。此外,它似乎是设计用于处理现有页面或资源加载中止而不是下一页。


0

我不相信可以以跨浏览器的方式检查用户是否点击了“停止”按钮,但是回到问题的根源,您可以监视请求本身:

当您运行xhr请求时,请使用onreadystatechange注册一个函数。检查xhr.readyState === XMLHttpRequest.DONE。检查您的指示器是否请求成功(手势编辑欢迎)。如果没有成功,则它被某种方式中断,您应该恢复进度指示器。

如果这是常见情况,您可以通过猴子补丁自动化此过程。请参见this question

如果这是POST请求,您还应该警告用户取消请求并不会阻止数据更改。您可以在这里变得更加复杂,并自动撤销POST请求或告诉他们确切地更改了什么,以便他们可以决定。

希望能有所帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接