Run loops are a fundamental part of any application framework. A short step-by-step listing of how SC.RunLoop works and what it is for, as explained by Erich Ocean at irc.freenode.net#sproutcore:
- the run loop starts whenever an event is received (a callback from the browser)
- you can start a run loop manually by calling SC.RunLoop.begin()
- the event is handled, which usually involves calling some code implemented by an app developer
- that code could cause observers to fire, and those observers can themselves be bindings
- bindings do not "fire" immediately
- instead, they add themselves to a buffer on the run loop
- when an app developer's code finishes running, the run loop will flush any pending bindings
- those bindings could cause more app developer code to run, more observers to fire, and more bindings to buffer
- but eventually, all of the bindings fire and there's no app developer code left to run
- at that point, three other buffers come into play: the DOM buffer, the layout buffer, and the render buffer
- SproutCore delays DOM modification, layout changes, and render updates until after all bindings have flushed
- it then performs them in that order
- (right before that, it invokes any methods that have been added to the run loop with "invokeOnce()"
- once that is done, SproutCore calls any invokeLast() methods
- finally, it checks to see if any SC.Timers should fire
- if so, it fires them
- otherwise, it does setTimeout() if there are any pending timers
- if not, it simply returns control to the browser, waiting for the next event/callback
- then it starts the run loop all over again