11

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

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

调用的事件trigger()是否会同步执行,从而保证在render()调用该行之前全部完成?

4

3 回答 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;
},

导入函数是triggerEvents,它实际上调用了处理程序。根据评论,它只是一个优化的调度程序。请注意,它们都在调用.call()and .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);
    }
};

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

于 2012-12-18T00:30:25.467 回答
2

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

于 2012-12-18T00:30:36.937 回答
1

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

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

于 2012-12-18T00:30:46.723 回答