¿Cómo "multidifundir" un iterable asincrónico?
¿Puede un asyncgenerador ser de alguna manera broadcast o multicast, de modo que todos sus iteradores ("consumidores"? ¿Suscriptores?) Reciban todos los valores?
Considere este ejemplo:
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('é', é);
})();
Las iteraciones "consumen" un valor, por lo que solo uno u otro lo obtiene. Me gustaría que ambos (y los posteriores) obtengan todos los yieldvalores ed, si es posible crear un generador de este tipo de alguna manera. (Similar a un Observable.)
Respuestas
Esto no es posible fácilmente. Necesitará ponerlo explícitamente en el tee . Esto es similar a la situación de los iteradores síncronos , solo que un poco más 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);
}
Debe asegurarse de que ambos iteradores se consuman aproximadamente a la misma velocidad para que el búfer no crezca demasiado.
¿Te refieres a esto?
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, é);
})();