【问题标题】:Handling of server-side HTTP 4nn/5nn errors returning a whole HTML document in jQuery's ajax requests处理在 jQuery 的 ajax 请求中返回整个 HTML 文档的服务器端 HTTP 4nn/5nn 错误
【发布时间】:2023-03-29 16:15:01
【问题描述】:

直截了当:您将如何处理 jQuery 的 ajax 请求中的服务器端 HTTP 4nn/5nn 错误?此案例涉及服务器端的 JSP/Servlet Web 应用程序。这里我不是在谈论诸如NullPointerException 等琐碎的运行时异常。假设它们都得到了完美的处理。这种 HTTP 4nn/5nn 错误的一个很好的例子是 401 未授权(用户权限不足)和 500 内部服务器错误(数据库关闭、I/O 错误、Errors 等)。假设它们不能(或不应该)在编码级别被捕获。

现在我刚刚在web.xml 中声明了一个<error-page> 用于此类错误。它基本上将请求转发到预定义的 JSP/HTML 错误页面,其中通知最终用户发生了严重错误,并且用户可以联系 xx@xx.xx 以获得进一步的帮助。同一页面还显示有关错误/异常的全局详细信息。

它在常规 HTTP 请求中完美运行,但是在使用 jQuery 的 XMLHtttp 请求中如何处理呢?什么是最适合用户体验的?对我来说,它只是显示整个错误页面,就好像它是一个普通的 HTTP 请求一样。我已经解决了如下:

function init() {
    $.ajaxSetup({
        error: handleXhrError
    });
}

function handleXhrError(xhr) {
    document.open();
    document.write(xhr.responseText);
    document.close();
}

虽然它工作得很好,但对我来说就像一个黑客。用 HTTP 错误页面的内容替换整个文档。但这也是你会遵循的方式吗?如果没有,您能否详细说明为什么不以及您更喜欢哪种方式?我看到的唯一替代方法是使用 JS 显示一些警报/消息框来通知用户有关无法解决的错误,但用户可以将其关闭并继续页面,而这是不可能的。

【问题讨论】:

  • 如果您使用自定义模式而不是 Alert,例如 jqModal 或 simpleModal,您可以将其设置为用户无法关闭/关闭它。如果错误不可恢复,您可以添加自己的按钮以将用户返回到主页、联系页面或您想要的任何其他页面。如果错误 is 可恢复(您提到数据库已关闭,可能会重新启动),那么一个不错的 Please wait and try again later 消息可能就足够了(允许用户关闭对话框并重试)。

标签: jquery jsp servlets error-handling


【解决方案1】:

毕竟,以与处理同步请求相同的方式处理异步请求的错误最有利于用户体验。只是,

function handleXhrError(xhr) {
    document.open();
    document.write(xhr.responseText);
    document.close();
}

当你有<script> 需要加载和初始化的元素时,IE6/7/8 将失败。 IE6/7/8 即不会那样做。为了让 IE 做到这一点,您基本上需要保留当前的<head> 元素,并且只用$("head").html(newHead) 替换它的子元素。 <body> 元素也应该这样做。

function handleXhrError(xhr) {
    var newDocument = xhr.responseText;
    $("head").html(newDocument.substring(newDocument.indexOf("<head>") + 6, newDocument.indexOf("</head>")));
    $("body").html(newDocument.substring(newDocument.indexOf("<body>") + 6, newDocument.indexOf("</body>")));
}

很糟糕,但是当响应文本代表一个带有头部和主体的整个 HTML 文档时,不可能执行 $(xhr.responseText)。当您在错误页面模板的&lt;body&gt; 上有一些属性(例如 ID、类等)时,不要忘记相应地更改子字符串索引。

【讨论】:

  • 它可能会让人觉得丑陋而不是 AJAX-y,但要对任何异常行为进行一致的处理,这是一致地处理 ajax 和直接服务器请求的唯一明智的方法。
【解决方案2】:

使用 JQuery 对话框,如下所示:

function handleXhrError(xhr) {
   ele = $("<div></div>").appendTo("body");
   ele.html(xhr.responseText);
   $(ele).dialog();

}

我应该回答你问的其余问题。我尽可能抛出和捕获特定异常,并向客户端发送特殊消息。有时我会指示客户端运行一个功能,该功能可能会重定向浏览器或部分刷新页面的一部分。这取决于具体情况。捕获 400/500 将处理真正的错误,但您还想编写一次 JS 代码来过滤您将从服务器返回的自定义错误标志的所有 AJAX 请求,请查看此页面以获取更多信息:http://www.bennadel.com/blog/1392-Handling-AJAX-Errors-With-jQuery.htm

【讨论】:

  • responseText 在这种情况下是一个有价值的 HTML 页面,有一个头部和一个主体,我不确定我是否更愿意将它放在一个对话框 div 中,上面只是替换文档。至于博客链接,抱歉,这对我没有任何价值。
  • 我忘了它是一个完整的 html 页面。我实际上在对话框中使用了 iframe,因此注入的 HTML 的样式不会干扰我的样式。至于链接,我只是建议您在应用程序的底层处理 AJAX 调用的返回函数调用。
【解决方案3】:

如有必要,您还应该能够重定向到您使用 window.location.href = "url-to-error-page"; 设置的预定义错误页面之一

【讨论】:

  • 这会触发一个新的 HTTP 请求,我不想在会话范围内存储有关错误/异常的详细信息。
  • 您希望显示有关错误/异常的哪些全局详细信息?我在想 401 的状态将重定向到实际的 401 页面,该页面将 401 标头连同它一起发送,对于 500 ...
【解决方案4】:

我认为最好发一条简短的信息,而不是完全重写您的页面。这样它就不会对页面本身产生太大影响。谷歌阅读器和 Gmail 做这样的事情。阅读器会显示消息并且不会将您的项目标记为已读,但您仍然可以阅读所有已加载的帖子。

【讨论】:

    【解决方案5】:

    在收到会导致不可用状态的错误情况后,您似乎希望保留工作页面/应用程序。

    我将在客户端实现状态历史记录并将页面恢复到最后可用状态,通过显着的页面内元素通知用户发生了什么。

    这背后的理论与交易有关。通常执行流程是:

    1. 指示事务管理器启动事务
      1. 开始交易
      2. 捕获状态
      3. 将控制权返回给调用代码
    2. 开始作为事务一部分的操作
    3. 发生错误:指示事务管理器回滚事务
      1. 将执行环境返回到上面捕获的状态
      2. 丢弃任何不再需要的数据(例如状态序列化)
    4. 成功时:指示事务管理器提交事务
      1. 根据需要完成事务中的操作
      2. 丢弃任何不再需要的数据

    我还没有认真研究过 javascript 中的事务管理。由于您声明服务器端错误使客户端无法使用,因此也许有一些方法可以在服务器端实现部分事务。重要的是,不要让事情只完成一半而不是在客户端。

    您是否考虑过在客户端应用程序尝试执行实际工作之前执行“飞行前检查”请求以尝试捕获这些问题?

    【讨论】:

    • 不,不是。我只是想与其他人分享经验,对于 unrecoverable 错误的最佳做法是在 ajax 请求 并且 返回的错误是一个完整的 HTML 页面的情况下。我在谷歌上搜索了很长时间,但我从未见过document.open()write(html)close() 的方法,所以我在这里有点闲逛。
    • 我明白了。我认为问题包括最好的用户体验是什么(是否显示完整的错误页面或允许某人继续)。如果你想让用户留在你的网站上,最好的体验是让他们继续他们正在做的事情,并尽可能提供一些关于避免错误的反馈。返回错误页面将导致刷新(如果这不会导致其搜索结果仍然存在的可用状态使用户感到沮丧,等等)和页面放弃......考虑客户端的表单预验证作为示例使用案例。
    猜你喜欢
    • 2010-09-20
    • 2017-05-14
    • 2015-07-12
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    相关资源
    最近更新 更多