2015-03-31 18 views
15

Sto provando a implementare un ciclo while usando le promesse.Mentre il ciclo utilizza bluebird promette

Il metodo descritto qui sembra funzionare. http://blog.victorquinn.com/javascript-promise-while-loop utilizza una funzione come questa

var Promise = require('bluebird'); 

var promiseWhile = function(condition, action) { 
    var resolver = Promise.defer(); 

    var loop = function() { 
     if (!condition()) return resolver.resolve(); 
     return Promise.cast(action()) 
      .then(loop) 
      .catch(resolver.reject); 
    }; 

    process.nextTick(loop); 

    return resolver.promise; 
}; 

Questo sembra utilizzare anti-pattern e metodi deprecati come cast e rinviare.

Qualcuno sa un modo migliore o più moderno per realizzare questo?

Grazie

+0

si può spiegare a parole cosa si sta realmente cercando di realizzare? Ricorda che un loop di attesa è una cosa orribile in Javascript. Ha molto più senso usare una sorta di gestore di eventi piuttosto che chiamare ripetutamente qualcosa in un ciclo chiuso. E cosa fa 'action()'? Forse mostrare un esempio di come lo useresti? – jfriend00

risposta

19

cast possono essere tradotti in resolve. defer dovrebbe indeed not be used.

Si dovrebbe creare il loop solo concatenando e annidando le chiamate then su un Promise.resolve(undefined) iniziale.

function promiseWhile(predicate, action, value) { 
    return Promise.resolve(value).then(predicate).then(function(condition) { 
     if (condition) 
      return promiseWhile(predicate, action, action()); 
    }); 
} 

Qui, sia predicate e action può restituire promesse. Per le implementazioni simili hanno anche uno sguardo a Correct way to write loops for promise. più vicino alla vostra funzione originale sarebbe

function promiseWhile(predicate, action) { 
    function loop() { 
     if (!predicate()) return; 
     return Promise.resolve(action()).then(loop); 
    } 
    return Promise.resolve().then(loop); 
} 
+0

è possibile modificare la funzione 'loop' per accettare un valore e quindi risolverlo quando il predicato è falso, solo per ottenere l'ultimo valore restituito dalla funzione' action'. – Sami

+0

@Sami: Sì, [la risposta nella domanda collegata] (http://stackoverflow.com/a/24660323/1048572) lo fa per esempio. Tuttavia volevo mantenere questa risposta vicino alla funzione OPs che risolve sempre a 'undefined' – Bergi

+0

Puoi mostrare un esempio del tuo' promiseWhile' in azione? Abbastanza confuso qui su come effettivamente usarlo. –

3

preferisco questa implementazione come il suo facile simulare pausa e continuare con esso:

var Continue = {}; // empty object serves as unique value 
var again = _ => Continue; 

var repeat = fn => Promise.try(fn, again) 
    .then(val => val === Continue && repeat(fn) || val); 

Esempio 1: si ferma quando l'origine o la destinazione indicano un errore

repeat(again => 
    source.read() 
    .then(data => destination.write(data)) 
    .then(again) 

Esempio 2: stop a caso se il coin flip dato il 90% di probabilità risultati spirito h un 0

var blah = repeat(again => 
    Promise.delay(1000) 
    .then(_ => console.log("Hello")) 
    .then(_ => flipCoin(0.9) && again() || "blah")); 

Esempio 3: Loop con condizione che restituisce la somma:

repeat(again => { 
    if (sum < 100) 
    return fetchValue() 
     .then(val => sum += val) 
     .then(again)); 
    else return sum; 
}) 
+1

Probabilmente userei un 'Simbolo' per un valore univoco, ma per il resto sembra buono :) –

+0

dio pensiero benji –

Problemi correlati