Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RxJS:保留输入顺序的MergeMap_Rxjs_System.reactive - Fatal编程技术网

RxJS:保留输入顺序的MergeMap

RxJS:保留输入顺序的MergeMap,rxjs,system.reactive,Rxjs,System.reactive,要求: // 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) URL=[url1、url2、url3] 并行激发所有3个URL,并在URL列表的sequence中绘制Dom

要求:

// 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)
URL=[url1、url2、url3]

并行激发所有3个URL,并在URL列表的sequence中绘制Dom

 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]
我的工作使用承诺:

// 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)
我想在可见光中做同样的事情

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

为了并行地激发它们,我使用了合并映射,但是如何对结果序列进行排序?

您可以使用fetch和paint,然后使用forkJoin/Promise来形成一个序列

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()

我找不到任何能维持秩序的东西,所以我想出了一些有点复杂的东西

const{concat,of,BehaviorSubject,Subject}=rxjs;
const{delay,filter}=rxjs.operators;
常量并行执行=(…obs$)=>{
const subjects=obs$.map(o$=>{
const subject$=新行为主体();
const sub=o$.subscribe(o=>{subject$.next(o);});
返回{sub:sub,obs$:subject$.pipe(filter(val=>val))};
});
const subject$=新主题();
亚组(0);
功能分组(索引){
常数当前=受试者[索引];
当前.obs$.subscribe(c=>{
主题$.next(c);
当前的.obs$.complete();
current.sub.unsubscribe();
if(指数<受试者长度-1){
分项指数(指数+1);
}否则{
主题$.complete();
}
});
}
返回主题$;
}
并行执行(
共(1)条管道(延迟(3000)),
第(2)款。管道(延迟(2000年)),
of(3).管道(延迟(1000))
).subscribe(结果=>{console.log(结果);})

对于像这样的异步任务,保持顺序的最佳方法是使用

问题是,如果我们单独应用它,我们将失去并行性。如果我们要这样做:

from(urls)
  .pipe(
      concatMap(x => fetch(x))
  )
在第一个请求完成之前,不会触发第二个请求

我们可以通过将地图拆分为自己的操作符来解决此问题:

from(urls)
  .pipe(
      map(x => fetch(x)),
      concatMap(x => x)
  )
所有请求都将同时触发,结果将按请求顺序发出

请参见下面适用于使用此方法的示例:

const{from}=rxjs;
const{concatMap,map}=rxjs.operators;
函数延迟承诺(val,延迟){
返回新承诺(res=>setTimeout(()=>res(val),delay));
}
无功延迟=3;
来自([1,2,3])管道(
映射(x=>delayPromise(x,延迟--*1000)),
concatMap(x=>x)
).subscribe(结果=>{console.log(结果);})

谢谢您的解决方案。但很抱歉,我只能接受一个答案。@pawankumar这很好,我只是想发布它,以防其他人发现这个问题。对不起,我不是那个意思,我发现你的答案比被接受的好得多。我想用一种有趣的方式说。是的,这应该是公认的答案。干得好。我刚刚看了这个视频,它让我想起了这个问题。这是代码