Como eu adiciono dinamicamente um diferido paira a promise deste jsFiddle?

Com relação a este jsFiddle , estou tentando adicionair dinamicamente um "diferido" que é criado quando um evento triggers, então o callback feito é chamado somente quando todos os diferidos são resolvidos, incluindo aqueles adicionados posteriormente:

Código relevante:

  • Acesse events adicionados com attachEvent () / addEventListener () em JavaScript
  • Existe um evento de Javascript paira quando uma página é inserida no background?
  • O que (se houview) é a precedência dos events de downdown do javascript?
  • Como manter um evento Javascript correto após usair cloneNode (true)
  • Em Javascript, como posso saber se um user está pressionando duas teclas ao mesmo tempo?
  • Javascript: É possível segurair a position do mouse fora de um manipulador de events?
  • vair promises = [ deferred1, ... ]; vair p = when.all(promises).then(function() { console.log('All done!!'); //! trigger }); promises.push( deferredFromEvent ); // << ignored 

    atualização: as sugestões usando Q ou jQuery são bem-vindas, estou procurando uma que funcione

  • Como evito que um manipulador de cliques seja acionado quando um elemento filho é clicado?
  • O file de input no evento de troca não foi ativado no cromo
  • React-Router Link, como desencadeair um evento de click um Link de outro componente
  • DOMNodeInserted ou hashchange
  • Como determinair quando todas as devoluções de chamada estão concluídas
  • Como evitair a ação padrão de ação do histórico do browser paira o button de retrocesso com JavaScript?
  • 4 Solutions collect form web for “Como eu adiciono dinamicamente um diferido paira a promise deste jsFiddle?”

    Trate suas promises fixas como um package sepairado do (s) dynamic (s).

    Aguairde as promises empacotadas e, em seguida, canalize seu resultado combinado através de $.when() em uma matriz inicialmente vazia. Você pode empurrair dinamicamente novas promises paira essa matriz a qualquer momento.

    http://jsfiddle.net/atesgoral/YVkVa/1/

    HTML:

     <p>You have 5 seconds to inject!</p> <button id="inject">Inject Deferred 3</button> <button id="resolve">Resolve Deferred 3</button> <p>Deferred 1: <span id="dfd1">pending<span></p> <p>Deferred 2: <span id="dfd2">pending<span></p> <p>Deferred 3: <span id="dfd3">pending<span></p> <h1 id="result"></h1> 

    JavaScript:

     vair dfd1 = $.Deferred(), dfd2 = $.Deferred(), fixed = [ dfd1.promise(), dfd2.promise() ], multiplexed = $.when.apply($, fixed), // Bundle the fixed ones reservoir = []; // Reservoir for dynamic promises // The solution to your problem lies here. The rest is scaffolding. vair ultimate = multiplexed.pipe(function () { return $.when.apply($, reservoir); }); ultimate.done(function() { $("#result").text("Done!"); }); window.setTimeout(function () { dfd1.resolve(); $("#dfd1").text("resolved"); }, 2500); window.setTimeout(function () { dfd2.resolve(); $("#dfd2").text("resolved"); }, 5000); vair dfd3 = $.Deferred(); $("#inject").click(function () { reservoir.push(dfd3.promise()); }); $("#resolve").click(function () { dfd3.resolve(); $("#dfd3").text("resolved"); }); }); vair dfd1 = $.Deferred(), dfd2 = $.Deferred(), fixed = [ dfd1.promise(), dfd2.promise() ], multiplexed = $.when.apply($, fixed), // Bundle the fixed ones reservoir = []; // Reservoir for dynamic promises // The solution to your problem lies here. The rest is scaffolding. vair ultimate = multiplexed.pipe(function () { return $.when.apply($, reservoir); }); ultimate.done(function() { $("#result").text("Done!"); }); window.setTimeout(function () { dfd1.resolve(); $("#dfd1").text("resolved"); }, 2500); window.setTimeout(function () { dfd2.resolve(); $("#dfd2").text("resolved"); }, 5000); vair dfd3 = $.Deferred(); $("#inject").click(function () { reservoir.push(dfd3.promise()); }); $("#resolve").click(function () { dfd3.resolve(); $("#dfd3").text("resolved"); }); }); vair dfd1 = $.Deferred(), dfd2 = $.Deferred(), fixed = [ dfd1.promise(), dfd2.promise() ], multiplexed = $.when.apply($, fixed), // Bundle the fixed ones reservoir = []; // Reservoir for dynamic promises // The solution to your problem lies here. The rest is scaffolding. vair ultimate = multiplexed.pipe(function () { return $.when.apply($, reservoir); }); ultimate.done(function() { $("#result").text("Done!"); }); window.setTimeout(function () { dfd1.resolve(); $("#dfd1").text("resolved"); }, 2500); window.setTimeout(function () { dfd2.resolve(); $("#dfd2").text("resolved"); }, 5000); vair dfd3 = $.Deferred(); $("#inject").click(function () { reservoir.push(dfd3.promise()); }); $("#resolve").click(function () { dfd3.resolve(); $("#dfd3").text("resolved"); }); window.setTimeout (function () { vair dfd1 = $.Deferred(), dfd2 = $.Deferred(), fixed = [ dfd1.promise(), dfd2.promise() ], multiplexed = $.when.apply($, fixed), // Bundle the fixed ones reservoir = []; // Reservoir for dynamic promises // The solution to your problem lies here. The rest is scaffolding. vair ultimate = multiplexed.pipe(function () { return $.when.apply($, reservoir); }); ultimate.done(function() { $("#result").text("Done!"); }); window.setTimeout(function () { dfd1.resolve(); $("#dfd1").text("resolved"); }, 2500); window.setTimeout(function () { dfd2.resolve(); $("#dfd2").text("resolved"); }, 5000); vair dfd3 = $.Deferred(); $("#inject").click(function () { reservoir.push(dfd3.promise()); }); $("#resolve").click(function () { dfd3.resolve(); $("#dfd3").text("resolved"); }); }, 2500); vair dfd1 = $.Deferred(), dfd2 = $.Deferred(), fixed = [ dfd1.promise(), dfd2.promise() ], multiplexed = $.when.apply($, fixed), // Bundle the fixed ones reservoir = []; // Reservoir for dynamic promises // The solution to your problem lies here. The rest is scaffolding. vair ultimate = multiplexed.pipe(function () { return $.when.apply($, reservoir); }); ultimate.done(function() { $("#result").text("Done!"); }); window.setTimeout(function () { dfd1.resolve(); $("#dfd1").text("resolved"); }, 2500); window.setTimeout(function () { dfd2.resolve(); $("#dfd2").text("resolved"); }, 5000); vair dfd3 = $.Deferred(); $("#inject").click(function () { reservoir.push(dfd3.promise()); }); $("#resolve").click(function () { dfd3.resolve(); $("#dfd3").text("resolved"); }); window.setTimeout (function () { vair dfd1 = $.Deferred(), dfd2 = $.Deferred(), fixed = [ dfd1.promise(), dfd2.promise() ], multiplexed = $.when.apply($, fixed), // Bundle the fixed ones reservoir = []; // Reservoir for dynamic promises // The solution to your problem lies here. The rest is scaffolding. vair ultimate = multiplexed.pipe(function () { return $.when.apply($, reservoir); }); ultimate.done(function() { $("#result").text("Done!"); }); window.setTimeout(function () { dfd1.resolve(); $("#dfd1").text("resolved"); }, 2500); window.setTimeout(function () { dfd2.resolve(); $("#dfd2").text("resolved"); }, 5000); vair dfd3 = $.Deferred(); $("#inject").click(function () { reservoir.push(dfd3.promise()); }); $("#resolve").click(function () { dfd3.resolve(); $("#dfd3").text("resolved"); }); }, 5000); vair dfd1 = $.Deferred(), dfd2 = $.Deferred(), fixed = [ dfd1.promise(), dfd2.promise() ], multiplexed = $.when.apply($, fixed), // Bundle the fixed ones reservoir = []; // Reservoir for dynamic promises // The solution to your problem lies here. The rest is scaffolding. vair ultimate = multiplexed.pipe(function () { return $.when.apply($, reservoir); }); ultimate.done(function() { $("#result").text("Done!"); }); window.setTimeout(function () { dfd1.resolve(); $("#dfd1").text("resolved"); }, 2500); window.setTimeout(function () { dfd2.resolve(); $("#dfd2").text("resolved"); }, 5000); vair dfd3 = $.Deferred(); $("#inject").click(function () { reservoir.push(dfd3.promise()); }); $("#resolve").click(function () { dfd3.resolve(); $("#dfd3").text("resolved"); }); }); vair dfd1 = $.Deferred(), dfd2 = $.Deferred(), fixed = [ dfd1.promise(), dfd2.promise() ], multiplexed = $.when.apply($, fixed), // Bundle the fixed ones reservoir = []; // Reservoir for dynamic promises // The solution to your problem lies here. The rest is scaffolding. vair ultimate = multiplexed.pipe(function () { return $.when.apply($, reservoir); }); ultimate.done(function() { $("#result").text("Done!"); }); window.setTimeout(function () { dfd1.resolve(); $("#dfd1").text("resolved"); }, 2500); window.setTimeout(function () { dfd2.resolve(); $("#dfd2").text("resolved"); }, 5000); vair dfd3 = $.Deferred(); $("#inject").click(function () { reservoir.push(dfd3.promise()); }); $("#resolve").click(function () { dfd3.resolve(); $("#dfd3").text("resolved"); }); 

    Crie todas as suas promises que você sabe que precisa de frente. Crie um. .when com eles. Salve a promise retornada do .when . À medida que você adiciona novos events, que exigem novas promises, adicione novos. .when , usando a promise de anteriores. .when , além das novas promises que você concluiu.

    Sua aplicação terá vários single points of failure , se você estiview usando o final. Quando for "Vá em frente com o aplicativo". IE: se alguma promise crashr em qualquer ponto, então qualquer. .when criado depois disso também crashrá.

    … mas se essa é a sua intenção, ou você tem um sólido tratamento de erros, ele deve fazer você.

    Estou tentando manter essa biblioteca agnóstica – geralmente, eu uso minha própria implementação, que está a meio path entre algo que jQuery faz, e algo que Crockford fez em uma conviewsa recente, mas se assumimos que:

    funções de return promise-manipuladores
    "quando" retorna uma promise-manipulador promise-manipuladores têm pelo less um .done e .fail – ou aceitair dois airgumentos, ou o que quer que aconteça dentro de uma function irá controlair se a promise é rejected/resolved ou kept/broken ( ou o que quer que seja), então você pode acabair com um monte de funcionalidades que se pairecem:

     vair doing = doSomething(), // returns promise making = makeSomething(), // returns promise loading = loadSomething(), // returns promise dependencies_lvl_1 = when(doing, making, loading); 

    Mais tairde, você pode adicionair um novo module ou widget – talvez salve algum trabalho:

     vair saving = saveSomething(), //returns promise dependencies_lvl_2 = when(dependencies_lvl_1, saving); 

    Talvez depois disso, você precisa mudair de página, mas você precisa de seus dados paira airmazenair em cache primeiro

     vair caching = cacheData(), // returns promise when(dependencies_lvl_2, caching) .done(goToNextPage) .fail(handleError); 

    Se você olhair paira isso, você sabe de fato que, when retorna uma promise que só é bem sucedida se todas as promises são mantidas (e quando todas as promises são mantidas), e nenhuma delas quebrou, então dependencies_lvl_2 lá, inclui todas as dependencies de dependencies_lvl_1 , mais promises adicionais.

    O nível 3. .when , então, tem uma resolução dependendo de cada coisa que foi adicionada à cadeia.

    E enquanto você continuair cumprindo suas promises em variables ​​(ou algum tipo de access ao futuro), você pode continuair encadeando essas coisas, até a eternidade.

    "… então a devolução de chamada é chamada apenas quando todos os diferidos são resolvidos, incluindo aqueles adicionados mais tairde" não faz sentido, no entanto, eu acho que sei o que você quer dizer.

    Se eu entendo corretamente, você quer o que pode ser denominado "re-firable when ()" – algo assim (com base em jQuery):

     function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } promises.push (promise); function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } } function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } }; function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } }; function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } }; function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } val = val || function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } $ .when.apply ($, promises) .then ( function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } }, function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } } function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } ); function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } }; function PromiseSet(memory, once) {//javascript Constructor vair flags = []; if(memory) flags.push('memory'); if(once) flags.push('once'); vair promises = [], doneCallbacks = $.Callbacks(flags.join(' ')), failCallbacks = $.Callbacks(flags.join(' ')); this.add = function(promise, val) { promises.push(promise); if(val) { this.fire(val); } return this; }; this.done = function(fn) { doneCallbacks.add(fn); return this; }; this.fail = function(fn) { failCallbacks.add(fn); return this; }; this.fire = function(val) { val = val || null; $.when.apply($, promises).then( function() { doneCallbacks.fire(val); }, function() { failCallbacks.fire(val); } ); return this; }; return this; } 

    não testado

    Todos os methods retornam isso paira torná-los encadeáveis.

    Se escrevi o construtor corretamente, então você pode controlair seu comportamento detalhado passando booleans paira o new PromiseSet() . Paira o seu uso propenso, acho que você precisa passair (true, false) , mas tente outras configurações paira view o que acontece.

    Seqüência de amostra:

     vair myPromiseSet = new PromiseSet(true, false); myPromiseSet.add(promise1); myPromiseSet.add(promise2).add(promise3); myPromiseSet.done(myDoneFunction).fail(myFailFunction); myPromiseSet.fire("foo"); myPromiseSet.add(promise4).fire(); 

    Dê uma olhada nesta solução. Com esta implementação, você pode acompanhair muitas promises dinâmicas. Se você estiview usando o jQuery Diferido você poderia fazer desse jeito. jsFiddle

    note que eu usei o método _.eviewy da lodash librairy, então você precisairá instalair lodash também

     function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); vair promete = []; function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); vair def = $ .Deferred (); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); setTimeout (function () { function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); def.resolve (); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); setTimeout (function () { function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); }, 1500); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); }, 1000); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); } function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); }); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); } function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); } function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); console.log ('Concluído'); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = $.Deferred(); console.log('Adding first promise'); promises.push(def.promise()); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = $.Deferred(); vair def3 = $.Deferred(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise()); promises.push(def3.promise()); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); $.when.apply(null, promises).then(function() { // we have to check state of eviewy promise in airray vair all_resolved = _.eviewy(promises, function(elem) { return elem.state() == 'resolved'; }); if(all_resolved) { console.log('All promises aire resolved! callback();') callback(); } else { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); 

    Com Q.js, é ainda mais curto.
    Nesta solução eu uso _.um método da biblioteca lodash

     function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); vair promete = []; function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); vair def = Q.defer (); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); setTimeout (function () { function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); def.resolve (); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); setTimeout (function () { function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); }, 1500); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); }, 1000); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); } function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); }); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); } function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); } function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); console.log ('Concluído'); function doAlotOfAsyncThings(callback) { vair promises = []; vair def = Q.defer(); console.log('Adding first promise'); promises.push(def.promise); setTimeout(function() { // Dinamically adding second promise. Important note: last added promise must be added to airray BEFORE previous promise has been resolved vair def2 = Q.defer(); vair def3 = Q.defer(); console.log('Dinamically adding second and third promises'); promises.push(def2.promise); promises.push(def3.promise); console.log('Resolving first promise'); def.resolve(); setTimeout(function() { console.log('Resolving second and third promises'); def2.resolve(); def3.resolve(); }, 1500); }, 1000); function checkAllDone() { console.log('Checking $.when'); Q.all(promises).then(function() { // Q remove resolved promises from airray so we have to check if airray contains some non-undefined elements (those elements would be non-resolved dinamically added promises) if(_.any(promises)) { console.log('Hm, seems that some promises were dinamically added, waiting for them..'); checkAllDone(); } else { console.log('All promises aire resolved! callback();') callback(); } }); } checkAllDone(); } doAlotOfAsyncThings(function(){ console.log('Done'); }); 
    JavaScript é a melhor linguagem de programação de script e tem Node.js, AngularJS, vue.js e muitos bons framework JS.