问题 Backbone的触发器()是同步还是异步?


我正在构建一个通用的Backbone视图来管理多个子视图。我有时需要执行逻辑来在渲染之前准备这些视图。我正在考虑使用Backbone事件启用pre_render挂钩,如下所示:

view = new (this.child_view);
this.trigger('pre_render', view);
view.render();

这些事件会被召集 trigger() 同步进行,从而保证他们都会在完成之前完成 render() 线被称为?


6028
2017-12-18 00:21


起源



答案:


基本上,是的,它是同步的。

以下是来源的相关部分:

trigger: function(name) {
  if (!this._events) return this;
  var args = slice.call(arguments, 1);
  if (!eventsApi(this, 'trigger', name, args)) return this;
  var events = this._events[name];
  var allEvents = this._events.all;
  if (events) triggerEvents(this, events, args);
  if (allEvents) triggerEvents(this, allEvents, arguments);
  return this;
},

导入功能是 triggerEvents,实际上调用处理程序。根据 注释,它只是一个优化的调度员。请注意,他们都在打电话 .call() 和 .apply(),所以回调将在控制权交还给调用者之前完成。

var triggerEvents = function(obj, events, args) {
    var ev, i = -1, l = events.length;
    switch (args.length) {
    case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx);
    return;
    case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0]);
    return;
    case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1]);
    return;
    case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1], args[2]);
    return;
    default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
    }
};

但是,正如其他人所提到的,触发处理程序可以自由地安排自己的回调,如果他们如此倾向。因此,处理程序在返回之前是否已完成其工作取决于处理程序代码本身。


12
2017-12-18 00:30





是的,它们是同步的。但是,此事件触发的功能可以免费使用 setTimeout 或者提出ajax请求,如果是这样的话,那些时候就不会完成了 trigger 调用返回,代码继续调用 render。所以是的每个绑定事件处理程序都是 调用 但不一定完成整套处理。因为触发器API本身不使用回调或承诺,所以没有直接的方法来知道所有事件处理程序何时完成。如果有必要,您必须自己实现这样的API,并在完成所有操作(包括任何异步处理)时触发一个独特的事件。但是,在日常编程中,大多数事件处理程序是同步的,如果不是,代码通常是这样的,即进行操作不会导致应用程序行为异常。如果您需要更改此合同,那么您的应用程序设计与使用事件系统并不一致的代码气味,您可能想要考虑不同的问题方法。


2
2017-12-18 00:30





触发器根据源代码是同步的,并不意味着所有侦听“pre_render”事件的函数都会执行同步操作 。 PS:源代码非常容易阅读,你应该看看它:

http://backbonejs.org/docs/backbone.html


1
2017-12-18 00:30



我肯定发现带注释的来源很有用;在回答这样的问题时,我大多喜欢留下纸条。谢谢! - Brad Koch


答案:


基本上,是的,它是同步的。

以下是来源的相关部分:

trigger: function(name) {
  if (!this._events) return this;
  var args = slice.call(arguments, 1);
  if (!eventsApi(this, 'trigger', name, args)) return this;
  var events = this._events[name];
  var allEvents = this._events.all;
  if (events) triggerEvents(this, events, args);
  if (allEvents) triggerEvents(this, allEvents, arguments);
  return this;
},

导入功能是 triggerEvents,实际上调用处理程序。根据 注释,它只是一个优化的调度员。请注意,他们都在打电话 .call() 和 .apply(),所以回调将在控制权交还给调用者之前完成。

var triggerEvents = function(obj, events, args) {
    var ev, i = -1, l = events.length;
    switch (args.length) {
    case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx);
    return;
    case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0]);
    return;
    case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1]);
    return;
    case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1], args[2]);
    return;
    default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
    }
};

但是,正如其他人所提到的,触发处理程序可以自由地安排自己的回调,如果他们如此倾向。因此,处理程序在返回之前是否已完成其工作取决于处理程序代码本身。


12
2017-12-18 00:30





是的,它们是同步的。但是,此事件触发的功能可以免费使用 setTimeout 或者提出ajax请求,如果是这样的话,那些时候就不会完成了 trigger 调用返回,代码继续调用 render。所以是的每个绑定事件处理程序都是 调用 但不一定完成整套处理。因为触发器API本身不使用回调或承诺,所以没有直接的方法来知道所有事件处理程序何时完成。如果有必要,您必须自己实现这样的API,并在完成所有操作(包括任何异步处理)时触发一个独特的事件。但是,在日常编程中,大多数事件处理程序是同步的,如果不是,代码通常是这样的,即进行操作不会导致应用程序行为异常。如果您需要更改此合同,那么您的应用程序设计与使用事件系统并不一致的代码气味,您可能想要考虑不同的问题方法。


2
2017-12-18 00:30





触发器根据源代码是同步的,并不意味着所有侦听“pre_render”事件的函数都会执行同步操作 。 PS:源代码非常容易阅读,你应该看看它:

http://backbonejs.org/docs/backbone.html


1
2017-12-18 00:30



我肯定发现带注释的来源很有用;在回答这样的问题时,我大多喜欢留下纸条。谢谢! - Brad Koch