Whenever I see code that goes like this:

// Make sure foo is closed. 
setTimeout(function () {  
  openNewFoo();
}, 150);

my spidey sense starts tingling. Why? Because coding that way too often leads to "followup" code that looks like this:

// Make sure foo is closed. 
setTimeout(function () {  
  openNewFoo();
}, 150);

// Make sure new foo is open
setTimeout(function () {  
  doBar();
}, 170);

Which is a sure one-way ticket to world full of a pain and a gordian knot of code where timeouts need to run after timeouts that need to run after timeouts. It's like an asynchronous goto.

As a programmer you should always be aware of the order of actions you need to execute. Your aim is to reduce complexity and allow fellow programmers (including future yourself) to reason about your code. This means you should prefer synchronous execution model whenever possible (simply because it's easier to follow).

Timeouts and debounces are an easy way out when you're in trouble because you need to carry out an action after another one or you want to prevent a function from being called too often (e.g. because it's called from two different places) - but more often than not it's the wrong solution. Like treating a symptom instead of the illness.

It's almost always possible to do away with setTimeout and _.debounce. If your code calls the same function from two places in quick succession perhaps those two places need to be more tightly coupled and made aware of each other. If you need to wait until something is rendered on the screen, Meteor offers the Tracker.afterFlush function.

setTimeout

setTimeout really should be reserved for operations that are explicitly time-dependent - such as when you want to run something every five minutes and you don't want to use setInterval (there are many legit cases where setInterval doesn't cut it).

Debouncing

Important point here: your app logic must work without debouncing. Yes, it may be unbearably slow but when you remove the _.debounce calls it must still run correctly. Debouncing is an optimisation, not a fix.

Typical usecases for debouncing are things like handling window resize events or saving editor content when user is typing - generally speaking you use it anywhere where you have to handle lots of events and you can safely ignore some of them plus your app doesn't need to react immediately. If you use _.debounce because for some reason your function is getting called more times than you expect, you're simply doing it wrong.

Happy coding! I'm @tomas_brambora.