Como “multicast” um iterável assíncrono?
Um asyncgerador pode ser de alguma forma broadcast ou multicast, de modo que todos os seus iteradores ("consumidores"? Assinantes?) Recebam todos os valores?
Considere este exemplo:
const fetchMock = () => "Example. Imagine real fetch";
async function* gen() {
for (let i = 1; i <= 6; i++) {
const res = await fetchMock();
yield res.slice(0, 2) + i;
}
}
const ait = gen();
(async() => {
// first "consumer"
for await (const e of ait) console.log('e', e);
})();
(async() => {
// second...
for await (const é of ait) console.log('é', é);
})();
As iterações "consomem" um valor, portanto, apenas uma ou outra o obtém. Eu gostaria que ambos (e quaisquer outros posteriores) obtivessem todos os yieldvalores de ed, se tal gerador for possível criar de alguma forma. (Semelhante a um Observable.)
Respostas
Isso não é facilmente possível. Você precisará fazer o tee explicitamente . Isso é semelhante à situação para iteradores síncronos , apenas um pouco mais complicado:
const AsyncIteratorProto = Object.getPrototypeOf(Object.getPrototypeOf(async function*(){}.prototype));
function teeAsync(iterable) {
const iterator = iterable[Symbol.asyncIterator]();
const buffers = [[], []];
function makeIterator(buffer, i) {
return Object.assign(Object.create(AsyncIteratorProto), {
next() {
if (!buffer) return Promise.resolve({done: true, value: undefined});
if (buffer.length) return buffer.shift();
const res = iterator.next();
if (buffers[i^1]) buffers[i^1].push(res);
return res;
},
async return() {
if (buffer) {
buffer = buffers[i] = null;
if (!buffers[i^1]) await iterator.return();
}
return {done: true, value: undefined};
},
});
}
return buffers.map(makeIterator);
}
Você deve garantir que ambos os iteradores sejam consumidos aproximadamente na mesma taxa para que o buffer não cresça muito.
Você quis dizer isso?
async function* gen() {
for (let i = 1; i <= 6; i++) yield i;
}
//const ait = gen();
(async() => {
// first iteration
const ait = gen()
for await (const e of ait) console.log(1, e);
})();
(async() => {
// second...
const ait = gen()
for await (const é of ait) console.log(2, é);
})();