I am trying to add batching capability to an async js generator. The idea is to have a function that would wrap around a non-batched generator. This function would call the generator's next method several times to launch several async operations concurrently, then it would return the first value taking care to refill the batch object as it returns its items to the client. The following examples demonstrates the working case that doesn't use the wrapper as well as the wrapper case that produces correct results, but doesn't result in desired behavior of concurrent execution of the batched promises.
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function foo(v) {
await sleep(1000);
return v;
}
const createAsyncGenerator = async function*(){
for (let i = 0; i < 5000; i++) {
yield foo(i);
}
}
const createBatchedAsyncGenerator = async function*(batch_size){
const batch = [];
for (let i = 0; i < batch_size; i++) {
batch.push(foo(i));
}
for (let i = batch_size; i < 500; i++) {
batch.push(foo(i));
yield batch.shift();
}
}
function batchAsyncGenerator(generator) {
return {
batch: [],
[Symbol.asyncIterator]() {
while (this.batch.length < 5) {
this.batch.push(generator.next());
}
return {
batch: this.batch,
async next() {
this.batch.push(generator.next());
const result = this.batch.shift();
return result;
}
}
}
}
}
const batching_works = async () => {
const asyncGenerator = createBatchedAsyncGenerator(5);
for await (const item of asyncGenerator) {
console.log(item)
}
}
const batching_doesnt_work = async () => {
const asyncGenerator = batchAsyncGenerator(createAsyncGenerator());
for await (const item of asyncGenerator) {
console.log(item)
}
}
batching_works()
//batching_doesnt_work()