0

So, I'm having a problem. I need to make potentially hundreds of http calls and they must be done one after the other. I also need to be able to interrupt the whole process at any time.

The solution I'm using right now is this one, but it doesn't allow me to properly interrupt the "chain" (I use jQuery and Deferreds because I haven't learned to replace them with Promises yet):

function doAnHttpCall() {
    return $.post('http://the.domain/theendpoint', { theParam: this });
}

var anArrayOfParams = ['param1', 'param2', 'param3'];

var p = $.Deferred();
setTimeout(p.resolve.bind(p), 0);

var promise = anArrayOfParams.reduce(function(prev, cur) {
    return prev.then(doAnHttpCall.bind(cur));
}, p)
.done(function() {
    console.log('all done.');
});

(I've found this solution here)

The problem here is that the only way to sort-of break out of the reduce function is by modifying the array you're looping through and check for a particular value and always return immediately when you find it, instead of executing the "doAnHttpCall" method (in this case). This would still make me loop over potentially hundreds of elements of the array instead of just interrupting the process, which is very ugly.

There must be a better way to do this. Or do I really need to use a function that calls itself with the next element to process when an http call has finished? It sounds "bad-practice-y".

Thanks for the help.

nonzaprej
  • 1,322
  • 2
  • 21
  • 30
  • 1
    Use a recursive approach instead. There's nothing about it that would make it a bad practice. – Bergi Apr 22 '18 at 16:54
  • 1
    `There must be a better way to do this` Yes, use `async` / `await`. Break works as you would expect.. – Keith Apr 22 '18 at 16:56
  • This is best done with recursive sequencing since reduce method will run up until the end. `async / await` is an imperative abstraction in which you can use `while` loops with a terminator condition to stop the loop. – Redu Apr 22 '18 at 18:30
  • Yes, thanks guys. I'm trying with `async` & `await`, I'll report back once I've managed to test the various scenarios. – nonzaprej Apr 22 '18 at 18:42

1 Answers1

1

You would use async/await:

const request = param => $.post('http://the.domain/theendpoint', { param });

(async () => {
  for(const param of ['param1', 'param2', 'param3']) {
    let result = await request(param);
    if (result === 'particular value') break;
  }
  console.log('all done!');
})();
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • Yep, this works for what I need to do, thanks. Just to add, for those who don't know: you can interrupt the loop by either returning something (which would trigger the `.then`) or by throwing an error (which would trigger the `.catch`). – nonzaprej Apr 22 '18 at 21:21