Необходимо понять, что в JavaScript вы всегда имеете дело с насосом событий: происходит какое-то событие браузера или истекает таймер, а затем исполняется часть JavaScript. Имея в виду эту модель выполнения, вы на самом деле не хотите думать о том, чтобы периодически происходил процесс пакетной обработки и отправки - вместо этого вы хотите объединить все вызовы, которые происходят в одном обработчике событий (фрагмент выполнения javascript в ответ на одно событие из браузера) и отправьте их.
Это делается путем изменения вашего кода rpc, чтобы каждый вызов помещал в очередь вызовы с параметрами и функциями обратного вызова в глобальный массив, а если он ставит в очередь первый вызов, он также назначает setTimeout(..., 0)
функцию, которая будет отправлять все в очереди и очистить массив.
Начните с этого, а затем вы можете поэкспериментировать с другими моделями выполнения, такими как запуск первого запроса сразу после его получения и отправка всего остального в пакете после выполнения текущего события.