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
});
Vielen Dank für die ausführliche Antwort! Ich habe dein letztes Beispiel benutzt. –