I know this is a pretty old question, but I came across a similar situation where there was still no easy solution that I could find.
I modified the existing quicksort and published a package that periodically terminates the EventLop: https://www.npmjs.com/package/qsort-async
If you are familiar with traditional quicksort, my only modification was the original function that performs the splitting. Basically, the function still modifies the array in place, but now returns a promise. It stops execution for other things in Eventloop if it tries to process too many elements in one iteration. (I believe that the default size that I specified was 10,000).
Note: it is important to use setImmedate here, not process.nextTick or setTimeout here. nextTick will actually put your execution in front of the IO of the process, and you will still have problems responding to other requests related to IO. setTimeout is too slow (I assume one of the other answers is related to the demo).
Note 2: If something like merge sort is more suitable for your style, you can do the same logic in this type of 'merge' function.
const immediate = require('util').promisify(setImmediate); async function quickSort(items, compare, left, right, size) { let index; if (items.length > 1) { index = partition(items, compare, left, right); if (Math.abs(left - right) > size) { await immediate(); } if (left < index - 1) { await quickSort(items, compare, left, index - 1, size); } if (index < right) { await quickSort(items, compare, index, right, size); } } return items; }
Full code here: https://github.com/Mudrekh/qsort-async/blob/master/lib/quicksort.js