Como sequencialmente executar promises com Q em JavaScript?

Eu estou tendo dificuldade em executar promises sequencialmente.

var getDelayedString = function(string) { var deferred = Q.defer(); setTimeout(function() { document.write(string+" "); deferred.resolve(); }, 500); return deferred.promise; }; var onceUponATime = function() { var strings = ["Once", "upon", "a", "time"]; var promiseFuncs = []; strings.forEach(function(str) { promiseFuncs.push(getDelayedString(str)); }); //return promiseFuncs.reduce(Q.when, Q()); return promiseFuncs.reduce(function (soFar, f) { return soFar.then(f); }, Q()); }; getDelayedString("Hello") .then(function() { return getDelayedString("world!") }) .then(function() { return onceUponATime(); }) .then(function() { return getDelayedString("there was a guy and then he fell.") }) .then(function() { return getDelayedString("The End!") }) 

onceUponATime () deve produzir sequencialmente [“Once”, “upon”, “a”, “time”], mas em vez disso eles estão sendo enviados imediatamente por algum motivo.

jsFiddle aqui: http://jsfiddle.net/6Du42/2/

Alguma ideia do que estou fazendo errado?

mas ao invés disso eles estão sendo enviados imediatamente por algum motivo.

Você está chamando-os já aqui:

 promiseFuncs.push(getDelayedString(str)); // ^^^^^ 

Você precisaria empurrar function(){ return getDelayedString(str); } function(){ return getDelayedString(str); } . Btw, em vez de usar o push para um array em each loop, você deve usar o map . E na verdade você realmente não precisa disso, mas pode reduce diretamente a matriz de strings :

 function onceUponATime() { var strings = ["Once", "upon", "a", "time"]; return strings.reduce(function (soFar, s) { return soFar.then(function() { return getDelayedString(s); }); }, Q()); } 

Ah, e não use document.write .