Given a function, fn
, which returns a promise, and an arbitrary length array of data (e.g. data = ['apple', 'orange', 'banana', ...]
) how do you chain function calls on each element of the array in sequence, such that if fn(data[i])
resolves, the whole chain completes and stops calling fn
, but if fn(data[i])
rejects, the next call fn(data[i + 1])
executes?
Here is a code example:
// this could be any function which takes input and returns a promise
// one example might be fetch()
const fn = datum =>
new Promise((resolve, reject) => {
console.log(`trying ${datum}`);
if (Math.random() < 0.25) {
resolve(datum);
} else {
reject();
}
});
const foundResult = result => {
// result here should be the first value that resolved from fn(), and it
// should only be called until the first resolve()
console.log(`result = ${result}`);
};
// this data can be purely arbitrary length
const data = ['apple', 'orange', 'banana', 'pineapple', 'pear', 'plum'];
// this is the behavior I'd like to model, only for dynamic data
fn('apple').then(foundResult)
.catch(() => {
fn('orange').then(foundResult)
.catch(() => {
fn('banana').then(foundResult)
.catch(() => {
/* ... and so on, and so on ... */
});
});
});
I feel like maybe there's an elegant solution to this pattern that I'm missing. The behavior is very similar to Array.some()
, but I've come up empty trying to fiddle with that.
EDIT: I switched from numeric data to string to stress that the solution needs to not be reliant on the data being numeric.
EDIT #2: Just to clarify further, fn
could be any function that accepts input and returns a promise. The fn
implementation above was just to give a complete example. In reality, fn
could actually be something like an API request, a database query, etc.