Вот функция, которая должна делать то, что вы хотите. Возможно, вы захотите изменить его так, чтобы он по-разному обрабатывал ошибочные предикаты.
Как уже отмечали другие, вы не можете "отменить" обещание, поскольку оно представляет собой нечто, что уже началось, вообще говоря.
/**
* Combines an array of promises with a predicate. Works like Promise.all, but checks each result from the given
* Promise against the supplied predicate, and if the result value from any Promise fails the predicate, the
* overall promise is immediatly resolved with those values which passed the predicate.
*/
function allWithPredicate(
promises /*: Array<Promise<T1>, Promise<T2>, ...> */,
predicate /*: (mostRecentResult, allResults, promiseIndex)*/
) /*: Promise<[T1, T2, ...]> */ {
// Handle empty input arrays
if (promises.length === 0)
return Promise.resolve([]);
// Create a manual result promise, as none of the built-in promise manipulation functions will do the trick.
return new Promise(
(resolve, reject) => {
// This array will collect the values from the promises. It needs to be the same size as the array of
// promises.
const results = new Array(promises.length);
// We track the number of resolved promises so we know when we're done. We can't use the length of the
// array above because the last promise might finish first, which would cause the array to be equal in
// length to the promises array.
let resolvedCount = 0;
// Now we go through each promise and set things up
promises.forEach(
(promise, index) => {
promise.then(
result => {
// A promise has finished successfully! Hooray. We increment the counter.
resolvedCount++;
// Now we check if the newly returned value from the promise is acceptable, using the
// supplied predicate.
if (predicate(result, results, index)) {
// If if it, we keep this result.
results[index] = result;
// If the resolved counter is equal to the original number of promises in the array,
// we are done and can return. Note that we do NOT check against the length of
// the promises array, as it may have been mutated since we were originally called.
if (resolvedCount === results.length) {
resolve(results);
}
} else {
// If not, we short-circuit by resolving the overall promise immediately.
// Note that as written, we do NOT include the unacceptable value in the result.
resolve(results);
}
},
error => {
reject(error);
}
)
}
)
}
);
}
Вот ссылка на демоверсию jsbin: https://jsbin.com/jasiguredu/edit?js,console