[英]Are methods bound to events called asynchronouly or not in Javascript / Backbone.js?
I am wondering if methods bound to events are called asynchronously or not in javascript? 我想知道绑定到事件的方法是否在javascript中异步调用? In my case I am using Backbone.js to build an app.
在我的情况下,我使用Backbone.js来构建一个应用程序。 I use an event aggregator to communicate between views.
我使用事件聚合器在视图之间进行通信。
If I have a method which triggers an event, will the methods in other views bound to that event complete before the rest of the method calling the trigger event is run? 如果我有一个触发事件的方法,那么在调用触发器事件的其余方法运行之前,其他视图中的方法是否会绑定到该事件?
Event aggregator is as follows: 事件聚合器如下:
var eventAggrigator = _.extend({}, Backbone.Events);
eventAggrigator.on('submitContactEditForm', function() {
console.log('Contact edit form submit event triggered');
});
Function call which triggers the event (this function is called from ViewA): 触发事件的函数调用(此函数从ViewA调用):
saveContact: function(event) {
var self = this;
// Prevent submit event trigger from firing.
event.preventDefault();
// Trigger form submit event.
eventAggrigator.trigger('submitContactEditForm');
// Update model with form values.
this.updateContact();
// Save contact to database.
this.model.save({
success: function(model, response) {
console.log('Contact ' + self.model.get('surname') + ' saved');
},
error: function(model, response) {
throw error = new Error('Error occured while saving contact.');
}
});
},
ViewB is bound to the event 'submitContactEditForm' (see relevant code from ViewB below): ViewB绑定到事件'submitContactEditForm'(参见下面ViewB中的相关代码):
initialize: function() {
_.bindAll(this, 'addSortableFields', 'appendNewField', 'getFieldsHtml', 'removeField', 'render', 'setEmailValues');
// Bind to event aggregator.
eventAggrigator.bind('submitContactEditForm', this.setEmailValues);
this.model = this.options.model;
},
setEmailValues: function() {
// Extract email form values.
var emails = _.clone(this.model.get('email'));
var emailFields = this.$('.email-field');
_.each(emails, function(email, index) {
email.value = emailFields.eq(index).val();
});
this.model.set('email', emails);
},
So the question would be, will ViewB.setEmailValues() always be completed before this.model.save() in ViewA.saveContact() is executed? 那么问题是,ViewB.setEmailValues()总是在ViewA.saveContact()中执行this.model.save()之前完成吗?
The relevant part where events are triggered in backbone is this: 在骨干中触发事件的相关部分是:
trigger: function(events) {
var event, node, calls, tail, args, all, rest;
if (!(calls = this._callbacks)) return this;
all = calls.all;
events = events.split(eventSplitter);
rest = slice.call(arguments, 1);
// For each event, walk through the linked list of callbacks twice,
// first to trigger the event, then to trigger any `"all"` callbacks.
while (event = events.shift()) {
if (node = calls[event]) {
tail = node.tail;
while ((node = node.next) !== tail) {
node.callback.apply(node.context || this, rest);
}
}
if (node = all) {
tail = node.tail;
args = [event].concat(rest);
while ((node = node.next) !== tail) {
node.callback.apply(node.context || this, args);
}
}
}
return this;
}
As you can see, event handlers are called synchronously one by one. 如您所见,事件处理程序是逐个同步调用的。
Warning: If your handlers make asynchronous calls, then of course these will not be guaranteed to complete before the execution stack continues after trigger
. 警告:如果您的处理程序进行异步调用,那么当然在执行堆栈在
trigger
后继续执行之前,这些将无法保证完成。 This, can be alleviated by the use of callbacks that would trigger completion or better by use of Deferred/Promises. 这可以通过使用将通过使用延迟/承诺触发完成或更好的回调来缓解。
It is a very interesting question with a very interesting answer. 这是一个非常有趣的问题,有一个非常有趣的答案。
I was expecting this behavior to be asynchronous but it turned out to be synchronous . 我期待这种行为是异步的,但事实证明它是同步的 。
I've based my conclusion in this code: 我在这段代码中得出了我的结论:
var MyModel = Backbone.Model.extend();
var oneModel = new MyModel();
oneModel.on( "event", eventHandler1 );
oneModel.on( "event", eventHandler2 );
function eventHandler1(){
for( var i = 0; i < 10; i++ ){
console.log( "eventHandler1", i );
}
}
function eventHandler2(){
for( var i = 0; i < 10; i++ ){
console.log( "eventHandler2", i );
}
}
function testEvent(){
console.log( "testEvent::INI" );
oneModel.trigger( "event" );
console.log( "testEvent::END" );
}
testEvent();
That results in this output: 这导致了这个输出:
testEvent::INI
eventHandler1 0
eventHandler1 1
eventHandler1 2
eventHandler1 3
eventHandler1 4
eventHandler1 5
eventHandler1 6
eventHandler1 7
eventHandler1 8
eventHandler1 9
eventHandler2 0
eventHandler2 1
eventHandler2 2
eventHandler2 3
eventHandler2 4
eventHandler2 5
eventHandler2 6
eventHandler2 7
eventHandler2 8
eventHandler2 9
testEvent::END
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.