New Feature: Timers
Speaking of Cocoa, I’ve added a new feature to SproutCore today very much inspired by Cocoa called Timers.
Timers are a better way to execute deferred code than setTimeout() and setInterval(), especially when you need to execute several different methods and you want them to stay in sync, such as during animation.
The problem with timeouts is that they are both inefficient and non-deterministic. That is, even if you set a timeout to execute in 100msec, you don’t know when the timeout will actually run. It may be 100msec, it may be 150msec, it may be 1500msec. Anything could happen. To make matters worse, browsers get really slow when they start executing lots of timeouts, meaning the time ranges when your timeouts execute will start to vary even more.
Although we can’t completely overcome the non-deterministic nature of timeouts, Timers at least make it better. Instead of setting one timeout per Timer, SproutCore sets only one timeout on an object called SC.runLoop. This object manages all of the timers you have registered in the system. When its timeout triggers, it will check your timers and fire any of them whose time has come. Since this is all done in the context of a single timeout handler, timers that are set to expire at the same time will tend to fire together just like you might expect.
In addition to providing a more consistent firing experience, Timers also schedule their time intervals based on when the run loop currently began running. This means that if you are in an event handler and you create three timers to fire in 100msec, they will all fire at the same time.
Using Timers is extremely simple. You can easily create them yourself (see the documentation here), or you can use the invokeLater() method defined on both objects an functions. Here is how you could invoke a method on an object after 100msec:
myObject.invokeLater('updateAnimation', 100) ;
If you just want to invoke a method the next runloop but as soon as possible, you can also omit the time:
myObject.invokeLater('updateAnimation');
Or sometimes you may have a function you’ve defined that you want to execute which is not attached to the object. You can do that too:
function() {
// handle animation
}.invokeLater() ;
If you want the function to execute in the context of an object you can do that also:
function() {
// handle animation
}.invokeLater(myView, 100);
In the past if you wanted your timeout function to execute in the context of a specific object, you had to use bind() which created a nasty closure to do its work. Thanks to the way timers are implemented, no closures are created during this process unless you pass a bunch of custom parameters (which is not the common case).
If you do want to pass custom parameters though, you can do so:
myObject.invokeLater('updateAnimationTo', 100, 'newState');
That’s it. Timers are really easy to use and much more performant than setting your own timeouts.

[...] abgearbeitet und anstehende Timeouts werden ausgelöst. Weitere Details dazu findet man in einem detailierten Blogpost im [...]