Является ли базовый триггер() синхронным или асинхронным?

Я создаю общий вид Backbone для управления несколькими дочерними представлениями. Иногда мне нужно выполнить логику, чтобы подготовить эти представления до их визуализации. Я рассматриваю возможность использования событий Backbone, чтобы включить hook_pender, например:

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

Будут ли выполняться события, вызываемые trigger() синхронно, тем самым гарантируя, что все они будут закончены до того, как вызывается строка render()?

Ответ 1

В принципе, да, это синхронно.

Здесь соответствующий раздел из источника:

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

Как отмечали другие, обработчики триггеров могут планировать собственные обратные вызовы, если они так склонны. Таким образом, будут ли обработчики закончить свою работу до возвращения, зависит от самого кода обработчика.

Ответ 2

Да, они синхронны. Однако функция, инициированная этим событием, может свободно использовать setTimeout или делать ajax-запросы, и если это произойдет, то они не будут завершены к моменту возврата вызова trigger, и код продолжит вызов render. Поэтому да, каждый обработчик связанных транзакций будет вызван, но не обязательно завершит весь свой набор обработки. Поскольку сам API-интерфейс триггера не использует обратные вызовы или promises, нет простого способа узнать, когда все обработчики событий завершены. При необходимости вам придется реализовать такой API самостоятельно и запустить отдельное событие, когда все будет сделано, включая любую асинхронную обработку. Тем не менее, при ежедневном программировании большинство этих обработчиков событий синхронны, а если нет, код обычно структурирован таким образом, что это не приведет к неправильной работе приложения. Если вам нужно изменить этот контракт, это запах кода, что дизайн вашего приложения не гармонично использует систему событий, и вам может понадобиться подумать о различных подходах к вашей проблеме.

Ответ 3

триггер синхронно в соответствии с исходным кодом, не означает, что все функции, которые прослушивают событие pre_render, будут выполнять синхронные операции, хотя , PS: исходный код очень прост для чтения, вам действительно нужно взглянуть на него:

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