Backbone的trigger()是同步还是异步的?

11

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

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

trigger()调用的事件会同步执行,从而保证它们都会在render()行被调用之前完成吗?

3个回答

12

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

以下是来源文件的相关部分:

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;
},

import函数是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);
    }
};

就像其他人提到的那样,触发器处理程序可以自由地安排它们自己的回调函数,如果他们愿意的话。因此,无论处理程序是否在返回之前完成工作是取决于处理程序代码本身的。


2
是的,它们是同步的。然而,由此事件触发的函数可以自由地使用setTimeout或进行ajax请求,如果这样做,那么在trigger调用返回并且代码继续调用render时,这些请求可能还没有完成。因此,是的,每个绑定的事件处理程序都将被调用,但不一定已经完成了其整个处理过程。由于trigger API本身不使用回调或承诺,因此没有直接的方法来知道所有事件处理程序何时完成。如果必要,您需要自己实现这样的API,并在完成所有异步处理(包括任何异步处理)后触发一个不同的事件。然而,在日常编程中,大多数事件处理程序都是同步的,如果不是,则通常结构化代码以使进展不会导致应用程序出现问题。如果您需要更改此合同,则这是您的应用程序设计不和谐使用事件系统的代码气味,您可能需要考虑不同的方法来解决问题。

1

根据源代码,触发器是同步的,但并不意味着所有监听“pre_render”事件的函数都会执行同步操作。

附注:源代码非常容易阅读,你应该真的看一下:

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


1
我肯定认为有注释的源代码很有用;当回答这类问题时,我大多数喜欢留下书面记录。谢谢! - Brad Koch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接