2
votes

RxJS: MergeMap avec conservation de l'ordre d'entrée

urls = [url1, url2, url3]

Déclenchez les 3 URL en parallèle et peignez le Dom dans l'ordre de la liste des URL p >

from(urls)
  .pipe(
      mergeMap(x => fetch(x))
  )

Mon travail avec des promesses:

// Fired all 3 urls at the same time
p1 = fetch(url1)
p2 = fetch(url2)
p3 = fetch(url3)

p1.then(updateDom)
  .then(() => p2)
  .then(updateDom)
  .then(() => p3)
  .then(updateDom)

Je voulais faire la même chose dans Observables.

 ex: Finished order of urls = [url3, url1, url2]
     when url1 finishes Immediately render the DOM, without waiting for url2
     If url2, url3 finishes before url1, then store url2, url3 and paint the DOM after url1 arrives
     Paint the DOM with order [url1, url2, url3]

Pour les lancer en parallèle, j'ai utilisé une carte de fusion, mais comment puis-je ordonner la séquence des résultats?


1 commentaires

Je viens de regarder cette vidéo et cela m'a rappelé cette question youtu.be/ZdS9uOl4OJk?t=2025 voici le code codesandbox.io/s/dreamy- bas-nmw6x? file = / src / ordersMergeMap.‌ ts


3 Réponses :


0
votes

Vous pouvez former une séquence avec fetch and paint puis forkJoin / Promise.all them

p1 = fetch(url1)
p2 = fetch(url2)
p3 = fetch(url3)

forkJoin(
from(p1).pipe(tap(_=>paint dom...))
from(p1).pipe(tap(_=>paint dom...))
from(p1).pipe(tap(_=>paint dom...))
).subscribe()


0 commentaires

1
votes

Je n'ai rien trouvé qui préserve l'ordre, alors j'ai trouvé quelque chose d'un peu compliqué.

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>
const { concat, of, BehaviorSubject, Subject } = rxjs;
const { delay, filter } = rxjs.operators;

const parallelExecute = (...obs$) => {
  const subjects = obs$.map(o$ => {
    const subject$ = new BehaviorSubject();
    const sub = o$.subscribe(o => { subject$.next(o); });
    return { sub: sub, obs$: subject$.pipe(filter(val => val)) };
  });
  const subject$ = new Subject();
  sub(0);
  function sub(index) {
    const current = subjects[index];
    current.obs$.subscribe(c => {
      subject$.next(c);
      current.obs$.complete();
      current.sub.unsubscribe();
      if (index < subjects.length -1) {
        sub(index + 1);
      } else {
        subject$.complete();
      }
    });
  }
  return subject$;
}


parallelExecute(
  of(1).pipe(delay(3000)),
  of(2).pipe(delay(2000)),
  of(3).pipe(delay(1000))
).subscribe(result => { console.log(result); });


0 commentaires

4
votes

4 commentaires

Merci pour la solution. Mais désolé, je ne peux accepter qu'une seule réponse.


@pawankumar c'est tout bon, je le postais juste au cas où d'autres personnes trouveraient cette question


Désolé, je ne voulais pas dire cela, j'ai trouvé votre réponse bien meilleure que celle acceptée. Je voulais dire cela d'une manière amusante.


Oui, cela devrait être la réponse acceptée. Bon travail.