emberjs/ember.js — Issue #364: Provide a way to schedule code to run immediately after the current run loop has committed
Author: robmonie
Created: 2012-01-09 08:44:56+00:00
State: open

There may already be a way to achieve this but nothing I can see satisfies my particular requirements. I want to be able to run some code in the current event loop immediately after the current run loop has ended. This guarantees that all bindings have propagated. Things i've tried so far include:

1. Using Ember.run.next - this works but is a smell in some cases. Any code that has to defer to the next event loop (as opposed to run loop) has consequences that are undesirable in some situations, particularly in unit testing where the deferring of code into the next event loop can cause all sorts of unexpected behaviour if not explicitly handled within the test itself.

2. Adding a custom queue to Ember.run.queues. This seemed like the obvious place, but i've found that this doesn't guarantee that the code will run after all bindings have synchronised. This surprised me as I thought that part of the reason for the queues existing was to make sure rendering only happened once the bindings had settled. Either i've misunderstood this or it's a bug. Could anyone confirm ??

I have created the following mechanism for achieving what I want in our app but I feel like this sort of thing should be baked into Ember if it's not already.

```coffeescript

afterCommitQueue = []

# functions scheduled after commit will be run in the order that they were put onto the
# queue immediately after the current run loop has ended. This is different from SC.run.next
# in that functions will be run in the current event loop instead of a future one. All functions executed
# from the afterCommitQueue will be run in a single run loop.
Ember.run.scheduleAfterCommit = (fn) ->
afterCommitQueue.push(fn)

originalRunloopEnd = Ember.run.end

Ember.run.end = ->
originalRunloopEnd()
if afterCommitQueue.length
Ember.run ->
while afterCommitQueue.length
fn = afterCommitQueue.shift()
fn.call(fn)
```