【问题标题】:Proper way to nest error messages while making asynchronous requests发出异步请求时嵌套错误消息的正确方法
【发布时间】:2023-11-28 04:41:01
【问题描述】:

当我发出一个同步的 jQuery ajax 请求时,我需要能够延迟向用户显示错误消息,直到我可以添加一些在我的错误函数上下文中不存在的更多信息。我正在尝试找到一种方法来抛出收集到的有关异常的信息,以便它可以被捕获到更高的链条上,并向用户显示更有意义的信息。我发现即使使用同步请求,当我在错误函数中放置一个 throw 语句时,我的包装 catch 块也不会捕获它。

      function GetFileName(entity, field, guid){
  var filename;
  try 
    {
      $.ajax({
            type: "GET",
            contentType: "application/json; charset=utf-8",
            datatype: "json",
            url: myURLwashere,
            beforeSend: function (XMLHttpRequest) {
                XMLHttpRequest.setRequestHeader("Accept", "application/json");
            },
            async: false,
            success: function (data, textStatus, xhr) {
                var result = data.d;
                filename = result[field];
            },
            error: function (xhr, textStatus, errorThrown) {
                throw  textStatus + " " + errorThrown;
                //entity, field and guid are null here
            }
        });
    }
    catch (err){
        //this catch block does not catch the exception thrown by the error function.
        throw "Error Getting File Name from web service for entity '" + entity + "' field '" + field + "' and guid '" + guid + "' (" + err.message + ")";
    }
    return filename;
  }

这是一个非常简单的例子。我可以通过几个函数嵌套好几层,并希望在向用户显示之前多次添加到错误消息中。

更新 我更新了问题以反映我的最终目标(嵌套错误处理),而不要求解决方案是同步的,这已被劝阻。

【问题讨论】:

  • 这个问题的答案很简单;您根本不应该进行同步 ajax 调用。
  • 关于同步请求:从 Gecko 30.0(Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27)开始,由于对用户体验的负面影响,主线程上的同步请求已被弃用。(来自 mdn)。
  • 明白。关于如何使用异步请求正确聚合嵌套调用中的良好错误消息的一些建议怎么样?

标签: javascript jquery ajax asynchronous error-handling


【解决方案1】:

我写这篇文章是为了回应特洛伊在 cmets 中提出的问题,“关于如何用异步请求正确聚合嵌套调用中的良好错误消息的一些建议怎么样?”

如果您之前没有做过太多的事件驱动(异步)编程,那么确实需要一点时间来适应。给自己找一个像这样的好的在线教程:http://code.tutsplus.com/tutorials/event-based-programming-what-async-has-over-sync--net-30027。如果您刚刚开始,您可能希望避免进入异步编程的 Deferred 或 Promise 模型。这些都是很棒的工具,但回调是一种更简单的开始方式。

将代码转换为异步的一种方法是为函数提供两个额外的“回调函数”参数:

function GetFileName(entity, field, guid, onSuccess, onError){

现在将async 更改为 true 并修改成功和错误函数,如下所示:

        async: true,
        success: function (data, textStatus, xhr) {
            var result = data.d;
            filename = result[field];
            onSuccess( filename );
        },
        error: function (xhr, textStatus, errorThrown) {
            // REMOVE: throw  textStatus + " " + errorThrown;
            //entity, field and guid are null here
            onError(textStatus, errorThrown);
        }

然后删除catch 块和return 语句。

这种风格会导致您重新设计甚至重新设计您当前的一些代码库。但正如其他人所指出的,使用同步 ajax 调用会造成非常糟糕的用户体验。

【讨论】:

  • 李。我了解如何传递一个在抛出错误时应该调用的函数。不过,我的同步大脑很难理解如何获得嵌套错误处理之类的行为。如果在发出请求时我有一些数据想要在请求出错时使用,那么持久保存它的最佳方法是什么?例如,我想用“无法获取实体 '123321' 的文件名”之类的好消息来包装丑陋的 textStatus,谢谢您的帮助。
  • Troy,您应该能够将 entity 作为参数传递给 onError 函数。我在您的原始代码中看到,当错误处理程序执行时,实体为空。这看起来很奇怪,因为错误函数是在 GetFileName 的闭包上下文中声明的。查看这个 jsfiddle 以了解我的意思:jsfiddle.net/kjsg4kkp/3