2016-04-29 7 views
1

Ich bin von Async Umwandlung drossel und kann nicht herausfinden, wie eine Schleife zu brecheneine Drossel .each() Prozess

Hier ist, was ich versuche zu erreichen:

  1. Schleife durch ein Array von Daten.
  2. Überprüfen Sie für jedes Element, ob es in DB vorhanden ist.
  3. Fügen Sie ein Element in den DB (erstes Element, das nicht existiert), und beenden Sie die .each() Schleife.

Jede Hilfe wird sehr geschätzt.

Antwort

4

Bluebird hat keine eingebaute Funktion für diese Art von Operation und es ist ein bisschen schwierig, in das Versprechen-Iterationsmodell zu passen, weil Iteratoren einen einzelnen Wert (ein Versprechen) zurückgeben, der Ihnen nicht wirklich die Möglichkeit gibt Kommunizieren Sie sowohl Erfolg/Fehler als auch Stopp Iteration.

Verwenden Ablehnung Iteration

stoppen Sie Promise.each() verwenden könnte, aber Sie würden eine codierte Ablehnung, um zu verwenden, um die Iteration wie diese zu stoppen:

var data = [...]; 

Promise.each(data, function(item, index, length) { 
    return checkIfItemExists(item).then(function(exists) { 
     if (!exists) { 
      return addItemToDb(item).then(function() { 
       // successfully added item to DB 
       // lets reject now to stop the iteration 
       // but reject with a custom signature that can be discerned from an actual error 
       throw {code: "success", index: index}; 
      }); 
     } 
    }) 
}).then(function() { 
    // finished the iteration, but nothing was added to the DB 
}, function(err) { 
    if (typeof err === "object" && err.code === "success") { 
     // success 
    } else { 
     // some sort of error here 
    } 
}); 

Diese Struktur könnte in eine wiederverwendbare Funktion/Methode einfügen, wenn Sie sie regelmäßig verwenden müssen. Sie müssen nur eine Konvention für ein abgelehntes Versprechen übernehmen, das wirklich nur die Iteration erfolgreich stoppen sollte, anstatt einen tatsächlichen Fehler.

Dies scheint eine interessante und nicht allzu ungewöhnliche Notwendigkeit, aber ich habe keine bestimmte definierte Struktur mit Promises für die Behandlung dieser Art von Problem gesehen.


Wenn es fühlt sich an wie ein, wie in dem obigen Szenario ablehnen Überlastung ist zu viel von einem Hack (was es Art der Fall ist), dann könnten Sie Ihre eigene Iterationsmethode schreiben, die einen aufgelösten Wert Konvention verwendet das zu sagen, Iterator, wenn zu stoppen:

Individuelle Iteration

Promise.eachStop = function(array, fn) { 
    var index = 0; 

    return new Promise(function(resolve, reject) { 

     function next() { 
      if (index < array.length) { 
       // chain next promise 
       fn(array[index], index, array.length).then(function(result) { 
        if (typeof result === "object" && result.stopIteration === true) { 
         // stopped after processing index item 
         resolve(index); 
        } else { 
         // do next iteration 
         ++index; 
         next(); 
        } 
       }, reject); 
      } else { 
       // finished iteration without stopping 
       resolve(null); 
      } 
     } 

     // start the iteration 
     next(); 
    }); 
} 

Hier, wenn der Iterator mit einem Wert aufgelöst wird, ein Objekt hat eine Eigenschaft stopIteration: true, dann wird der Iterator zu stoppen.

Die endgültige Zusage wird abgelehnt, wenn irgendwo ein Fehler auftritt, und wird mit einem Wert von null aufgelöst, wenn der Iterator beendet und nie gestoppt wurde oder mit einer Zahl, die der Index ist, an dem die Iteration gestoppt wurde.

Sie würde das wie folgt verwenden:

Promise.eachStop(data, function(item, index, length) { 
    return checkIfItemExists(item).then(function(exists) { 
     if (!exists) { 
      return addItemToDb(item).then(function() { 
       // return special coded object that has stopIteration: true 
       // to tell the iteration engine to stop 
       return {stopIteration: true}; 
      }); 
     } 
    }) 
}).then(function(result) { 
    if (result === null) { 
     // finished the iteration, but nothing was added to the DB 
    } else { 
     // added result item to the database and then stopped further processing 
    } 
}, function(err) { 
    // error 
}); 

Flag-Variable, die Iterator Ob erzählt seine Arbeit

In Gedanken über diese etwas mehr zu überspringen, kam ich mit einem anderen Weg nach oben Dazu muss die Iteration Promise.each() ausgeführt werden, aber eine höhere Bereichsvariable festgelegt werden, die Ihrem Iterator sagt, wann er seine Arbeit überspringen soll:

var data = [...]; 
// set property to indicate whether we're done or not 
data.done = false; 

Promise.each(data, function(item, index, length) { 
    if (!data.done) { 
     return checkIfItemExists(item).then(function(exists) { 
      if (!exists) { 
       return addItemToDb(item).then(function() { 
        data.done = true; 
       }); 
      } 
     }) 
    } 
}).then(function() { 
    // finished 
}, function(err) { 
    // error 
}); 
+0

Vielen Dank für die ausführliche Antwort! Ich habe dein letztes Beispiel benutzt. –