代码之家  ›  专栏  ›  技术社区  ›  Mike Spross Alex Martelli

API设计:如何从异步xmlhttp调用中处理不同的错误类?

  •  0
  • Mike Spross Alex Martelli  · 技术社区  · 16 年前

    我有一个旧的vb6应用程序,需要对Web服务进行异步调用。Web服务提供 search 方法允许最终用户查询中央数据库并查看应用程序中的结果。我正在使用 MSXML2.XMLHTTP 提出请求,并写了 SearchWebService 类,该类封装Web服务调用和代码以不对称地处理响应。

    目前, 搜索Web服务 向调用方引发两个事件之一: SearchCompleted SearchFailed . 一 搜索已完成 如果调用成功完成,则将引发包含搜索结果的事件,该结果位于事件的参数中。一 搜索失败 在检测到任何类型的故障时引发,这可能是从格式不正确的URL(这可能是因为该URL是用户可配置的)到低级网络错误(如“找不到主机”)到HTTP错误(如内部服务器错误)。它向最终用户返回错误消息字符串(如果存在,则从Web服务响应正文中提取,如果响应没有正文,则从HTTP状态代码文本中提取,如果发生网络错误,则从网络错误代码中转换)。

    由于各种安全要求,调用应用程序不直接访问Web服务,而是通过客户站点上运行的代理Web服务器访问,而代理Web服务器又通过VPN访问实际的Web服务。但是, 搜索Web服务 不知道调用应用程序正在通过代理访问Web服务:它只是被提供了一个URL,并被告知发出请求。代理的存在是应用程序级别的要求。

    问题在于,从最终用户的角度来看,调用应用程序必须能够区分低级网络错误和Web服务的HTTP错误,并区分代理错误和远程Web服务器错误。例如,应用程序需要知道请求是否因代理服务器关闭或代理访问的远程Web服务关闭而失败。在每种情况下,都需要向最终用户显示特定于应用程序的消息,例如“搜索Web服务代理服务器似乎已关闭”。代理服务器可能需要重新启动“与”代理当前正在运行,但远程Web服务器似乎不可用。请联系(远程Web服务器负责人的姓名)。“我可以直接在 搜索Web服务 类,但从此类通用类生成这些特定于应用程序的错误消息似乎是错误的(该类可能用于不需要代理的环境中,在这种环境中错误消息将不再有意义)。

    这种区别对于故障排除很重要:代理服务器问题通常可以由客户解决,但远程Web服务器错误必须由第三方处理。

    我在想解决这个问题的方法之一是 搜索Web服务 类检测不同类型的错误,并在每种情况下引发不同的事件。例如,而不是单个 搜索失败 活动,我可以 NetworkError 低级网络错误事件(表示访问代理服务器时出现问题),a ConfigurationError 上的无效属性的事件 搜索Web服务 类(例如传递格式不正确的URL)和 ServiceError 对于远程Web服务器上发生的错误(意味着代理正常工作,但远程服务器返回了错误)。

    现在我考虑一下,还有一个额外的错误场景:代理服务器可能运行正常,但是远程Web服务器关闭,或者代理服务器配置错误。

    使用多个错误事件对不同类别的错误进行分类的方法是否是解决这个问题的合理方法?对于上一个场景(代理正在运行,但无法访问远程服务器),我想我可能需要设置代理以返回特定的HTTP错误代码,以便客户端能够检测到这种情况(即比500响应更具体的情况)。

    原来我是单身 搜索失败 只需添加一个 errorCode 事件的参数,但这很快变得混乱,尤其是在没有逻辑错误代码可供使用的情况下(例如,如果vb6引发“实际”错误,即如果xmlhttp类未注册)。

    1 回复  |  直到 16 年前
        1
  •  1
  •   djna    16 年前

    我认为我在Java异常中使用的一些想法可能在这里适用。

    有大量不同的异常会变得相当混乱,但是我们需要向用户提供足够的细节,这样我们就不想丢失信息。

    因此,我有一些特定的例外情况,我想这与您的事件相对应:

    • InvalidRequestEvent:当用户指定错误信息时使用
    • TransiterErrorEvent:在基础结构出现问题时使用,此时重试可能有效。

    我倾向于在我们有服务器集群的环境中工作,所以如果用户请求碰到一个即将死亡的服务器,那么如果他重新提交,他可能会得到一个好的服务器,因此从他的角度来看,简单的重试通常是可行的。但是,有时错误出现在网络或数据库等服务上,在这种情况下,用户需要诊断信息向帮助台报告。因此,我们需要决定将额外的信息放入异常中。这是(如果我理解正确的话)你的问题。

    在InvalidRequestException的情况下,我们打赌会给出关于输入问题的一些信息。它可能在“不匹配的括号”或“表顺序中未知的列切割器”的行中。在TransientErrorException的情况下,它可能是“代理服务器已关闭”。

    现在,根据您的具体要求,您可能实际上没有选择将该文本放入异常中,而是选择一个错误号,表示层将该错误号转换为特定于区域设置的字符串(英语、法语…)。

    因此,任何一个异常都可能包含这样的内容(对于Java语法很抱歉,但我希望这个想法是明确的):

    BaseException {
        String ErrorText;     // the error text itself
    
        // OR if you want to allow for internationaliation
    
        int ErrorCode;        // my application specific code, corresponds to text held by the UI
        String[] params;      // specific parameters to be substitued in the error text
                              // CUTSOMER and ORDER in my example above
    
    
        int SystemErrorCode;    // If you have an underlying error code it goes here
    
    
        String SystemErrorText; // any further diagnoistic you might need to give to 
                                // the user so that they can report the problem to the 
                                // help desk.
    
        // OR instead of the text (this is something I've seen done)
    
        int SystemErrorTag;     // A unique id for this particular error problem. 
                                // This server systems will label their message in the
                                // server logs. Users just tell the help desk this number
                                // they don't need to read detailed server error text.
    

    }