DJWassink / Promise-parallel-throttle

It's kinda like Promise.all(), but throttled!
MIT License
81 stars 3 forks source link

Return results after reject with failFast:true? #27

Closed kodie closed 6 years ago

kodie commented 6 years ago

I'd like to have the Promises stop after the first error, however I'd like to return whatever results that were returned before that. Is this possible?

I've tried this with no success:

var rows = []
var queue = Array.from({ length: addPagesToLoad }, (v, k) => () => this.load(tab, (k + 2)))

return Throttle.all(queue, { maxInProgress: this.throttle })
  .catch(e => {
    if (this.debug) console.error(e.response)
    return queue
  })
  .then(results => {
    for (var i = 0; i < results.length; i++) {
      rows = rows.concat(this.extract(results[i], callback))
    }

    if (limit) return rows.slice(0, limit)
    return rows
  })

Any ideas? Thanks in advance!

DJWassink commented 6 years ago

Hey, thanks for trying this lib 😄

The all method is pretty limited in customizations, so instead of the all you might want to use the raw method instead which will return a result object instead of throwing the error.

Try the following code:

import * as Throttle from 'promise-parallel-throttle';

const names = [
  { firstName: 'Irene', lastName: 'Pullman' },
  { firstName: 'Sean', lastName: 'Parr' },
  { firstName: 'Joe', lastName: 'Slater' },
  { firstName: 'Karen', lastName: 'Turner' },
  { firstName: 'Tim', lastName: 'Black' }
];

const combineNames = (firstName, lastName) => {
  return new Promise((resolve, reject) => {
    if (firstName === 'Joe') {
      reject(new Error());
    } else {
      resolve(firstName + ' ' + lastName);
    }
  });
};

//Create a array of functions to be run
const tasks = names.map(u => () => combineNames(u.firstName, u.lastName));

(async () => {
  try {
    const { taskResults: formattedNames } = await Throttle.raw(tasks, { maxInProgress: 1, failFast: true });
  } catch (failed) {
    console.info(failed);
  }
})();
kodie commented 6 years ago

That works great!

I modified your code a little to suit my needs:

const runTasksUntilError = async (...args) => {
  args[1] = Object.assign(args[1] || {}, { failFast: true })

  try {
    const { taskResults } = await Throttle.raw(...args)
    return taskResults
  } catch (raw) {
    const err = raw.taskResults.splice(raw.rejectedIndexes[0], 1)[0]
    console.error(err)
    return raw.taskResults
  }
}

runTasksUntilError(tasks, { maxInProgress: 10 })
  .then(r => {
    console.log(r)
  })

Thank you!