afterPreviousEvents
Run code when all previuos state has settled.
canBatch.afterPreviousEvents(handler)
Calls handler
when all previously [can-event/batch/batch.trigger triggered] events have
been fired. This is useful to know when all fired events match the current state.
Parameters
- handler
{function}
:A function to call back when all previous events have fired.
Use
With batching, it's possible for a piece of code to read some observable, and listen to changes in that observable, but have events fired that it should ignore.
For example, consider a list widget that creates <li>
's for each item in the list and listens to
updates in that list and adds or removes <li>
s:
var makeLi = function(){
return document.createElement("li")
};
var listWidget = function(list){
var lis = list.map(makeLi);
list.on("add", function(ev, added, index){
var newLis = added.map(makeLi);
lis.splice.apply(lis, [index, 0].concat(newLis) );
}).on("remove", function(ev, removed, index){
lis.splice(index, removed.length);
});
return lis;
}
The problem with this is if someone calls listWidget
within a batch:
var list = new DefineList([]);
canBatch.start();
list.push("can-event","can-event/batch/");
listWidget(list);
canBatch.stop();
The problem is that list will immediately create an li
for both can-event
and can-event/batch/
, and then,
when canBatch.stop()
is called, the add
event listener will create duplicate li
s.
The solution, is to use afterPreviousEvents
:
var makeLi = function(){
return document.createElement("li")
};
var listWidget = function(list){
var lis = list.map(makeLi);
canBatch.afterPreviousEvents(function(){
list.on("add", function(ev, added, index){
var newLis = added.map(makeLi);
lis.splice.apply(lis, [index, 0].concat(newLis) );
}).on("remove", function(ev, removed, index){
lis.splice(index, removed.length);
});
});
return lis;
}