3

这个问题是关于 Backbone 0.9.2

自从升级到 Backbone 0.9.10 后,我们选择覆盖 Backbone.sync,它就像一个魅力。

  • 2012 年12 月- (v0.9.9) Backbone.wrapError 已被删除。
  • 2013 年2 月- 看起来 WrapError 将在 Backbone 的下一个版本中恢复,但覆盖主干.sync 是要走的路。


(抱歉读了很久)

我正在修改 Backbone.wrapError 函数,我被一行字弄糊涂了。我知道这条线的作用,但不知道为什么它是必要的。

  resp = model === originalModel ? resp : model;
  • resp 最终成为 textStatus/errorType 即:“错误”“超时”“解析错误”
  • model 是 XHR 请求对象
  • originalModel 是对最终调用此函数的 Backbone.Model 实例的引用

我很好地掌握了 Backbone.wrapError 的作用、返回的内容以及使用方式,但我似乎无法理解上述行的目的。


Backbone 的文档指出 wrapError 将“使用回退错误事件包装可选的错误回调”,这是真的。此外,我了解到 Backbone.wrapError 在库中从 fetch、save、destroy 和 reset 函数中调用了 4 次,以确保库不会忽视 AJAX 错误。例如,如果将 AJAX 错误回调传递给 fetch 方法,它将使用传递的几个参数执行,如果没有,模型将使用传递的相同的几个参数触发错误事件。

示例调用:

options.error = Backbone.wrapError(options.error, model, options);

Backbone.wrapError:

  Backbone.wrapError = function(onError, originalModel, options) {
    return function(model, resp) {
      resp = model === originalModel ? resp : model;
      if (onError) {
        onError(originalModel, resp, options);
      } else {
        originalModel.trigger('error', originalModel, resp, options);
      }
    };
  };

这行 ( resp = model === originalModel ? resp : model;) 出现的问题是 model 和 resp 对应于 jQuery/Zepto 错误回调参数列表中的前 2 个参数。我遇到的第一个问题是这些参数(模型、响应)的命名,因为在调试时我已经看到这两个参数是jqXHR/xhrand textStatus/errorType。textStatus/errorType 参数通常最终是“错误”,但(根据文档)也可以是“超时”“解析错误”等。比较model === originalModel对我来说毫无意义。对 XHR 对象和 Backbone.Model 实例的硬比较总是会失败,并且model会存储到response(resp) 中,这很好,因为model实际上是 XHR 响应对象...这行对我来说似乎毫无意义,但我继续将其包含在我修改后的 wrapError 方法中。

因为model === originalModel总是评估为假,所以该行似乎是 resp = model; 的复杂版本。这是没用的,因为您可以完全删除该行,并且model可以将参数传递给originalModel.trigger('error', originalModel, resp, options);而不是resp.

有没有model === originalModel可能评估为真的实例?

任何在 Backbone.js、AJAX 方面有更多经验的人都可以回答/解释为什么这条线是必要的?

4

1 回答 1

4

TLDR/悬崖:

下面奇怪的小线用于确定错误回调是由模型级别的验证失败或来自 fetch、save 或 destroy 方法(均调用 Backbone.sync)的失败 AJAX 调用触发的天气。如果失败来自验证,它不会更改 resp 变量,因为 resp 应该已经保存了 validate 返回的有用信息(例如错误数组或有关错误的字符串)。如果失败来自错误的 AJAX 请求,则 XHR 对象将存储到 resp 中,因为 XHR 是可用信息最多的项目。不幸的是,XHR 作为模型传递给这个函数,Backbone 文档没有指出这个参数并不总是代表一个模型。Resp 旨在保存有关错误的有用响应信息,并发送到错误回调或抛出的错误事件。


好的。我学到了一些关于这条奇怪的线的东西。

resp = model === originalModel ? resp : model;

在 Backbone 中有 AJAX 错误和验证错误。方便的是,Backbone 将两个错误集中到同一个函数中——AJAX 错误回调。问题是传递给这些函数的参数不一致。当出现 AJAX 错误时,XHR 对象可用,但在验证错误期间不可用。

  • 如果不存在回调,Backbone 将抛出和“错误”事件,其参数与传递给错误回调的参数相同。(下面的第 7 行和第 9 行)。

在成功的 AJAX 请求之后,您的 JSON 数据可以选择性地通过模型的 validate 函数。在 Backbone 中,验证功能should return false or nothing at all when there are no errors。当出现错误时,通常会返回一个数组,例如['invalid username', 'password too long', 'etc...']从 validate 返回的任何内容(通常是错误消息数组)作为resp参数传递到“包装”错误回调中,模型本身作为model!

_validate 函数有点草率,有多个 return 语句,但是当验证失败时,第 9 行被命中。函数的第 9 行_validate通过this(模型)、error(从模型验证方法返回)、options(ajax 选项、成功、错误、超时等)。这不同于将传入xhr(xmlhttprequest 对象)、errorType('error' 'timeout' 'parse error' 等)、options(ajax 选项)的 AJAX 错误。

validate error:   error(model, validate_return_value, options)
    ajax error:   error(xhr, errorType, options)

1   _validate: function(attrs, options) {
2     if (options.silent || !this.validate) return true;
3     attrs = _.extend({}, this.attributes, attrs);
4     var error = this.validate(attrs, options);
5     if (!error) return true;
6     if (options && options.error) {
7*       options.error(this, error, options);
8     } else {
9       this.trigger('error', this, error, options);
10    }
11    return false;
12  }

上面奇怪的代码行是必要的,因为这个函数处理来自 2 种不同方法的错误。AJAX 和验证。这两个向它发送不同的参数,因此这是为了规范它们并使用一致的参数列表抛出事件。

When a validation error occurs, the model does not change所以model传递给错误回调的那个完全等于originalModel. 该resp参数的目的是保存有关错误本身的信息。当出现 AJAX 错误时,“超时”“解析错误”或“错误”根本不如 XHR 对象提供信息。

那条奇怪的小线决定了错误回调是从_validate或通过诸如 404 之类的正常 AJAX 错误访问的天气。当从 validate 访问它时,是从 validateresp返回的值。它应该是前端模板显示的信息丰富且有用的数据。当结果错误来自 HTTP 错误时,有关该错误的最有用信息是作为 MODEL 参数传递到此函数的 XHR 对象。

wrapError 和 validate 函数的一种有希望的简化方法

   Backbone.wrapError = function(ajax_error_callback, model_or_xhr, ajax_options) {
      return function(model_or_xhr, error_info) {
        if there was an ajax error, error_info = the xhr object
        if there was a validation error, error_info = whatever was returned from validate
        if there's an error callback {
          run the error callback with (the original model, error_info, ajax_options)  as parameters
        if there is not an error callback
          throw an event called 'error' with (the original model, error_info, ajax_options) as parameters
        }
      };
    };

原来的:

   Backbone.wrapError = function(onError, originalModel, options) {
      return function(model, resp) {
        resp = model === originalModel ? resp : model;
        if (onError) {
    *      onError(originalModel, resp, options);
        } else {
          originalModel.trigger('error', originalModel, resp, options);
        }
      };
    };

* 表示从这里调用的错误回调

于 2012-09-13T19:51:23.337 回答