Является ли базовый триггер() синхронным или асинхронным?
Я создаю общий вид 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