Javascript 如何展平RXJS中的嵌套调用并最终调用最后一个调用?

Javascript 如何展平RXJS中的嵌套调用并最终调用最后一个调用?,javascript,asynchronous,callback,rxjs,nested,Javascript,Asynchronous,Callback,Rxjs,Nested,我们如何才能最好地将下面的呼叫扁平化。RxJS新手,试图理解如何简化它。阅读flatMap、forkJoin、switchMap和mergeMap,没有找到正确的路径来集成下面的内容,也不确定下面的场景中哪一个是最好的 const useful = []; a.get('abc'). subscribe((abcdatas) => { abcdatas.forEach(abcdata => { if(abcdata.exist) { b.get('

我们如何才能最好地将下面的呼叫扁平化。RxJS新手,试图理解如何简化它。阅读flatMap、forkJoin、switchMap和mergeMap,没有找到正确的路径来集成下面的内容,也不确定下面的场景中哪一个是最好的

const useful = [];

a.get('abc').
subscribe((abcdatas) => {

   abcdatas.forEach(abcdata => {
     if(abcdata.exist) {
        b.get('def').
        subscribe((defdatas) => {
           useful.push(defdatas.someval);
        });
      } 
   });

 })

if(useful.length) {
 c.get('ghi').
 subscribe((ghidata) => {
   completed...
 });
}
使现代化 更新我的问题,谢谢你的回复。有用的是一个结果的全局数组,在我的例子中,应该从嵌套调用填充该数组。最后应该传递给最后一个调用

我正在尝试的步骤:

  • a、 get()=>返回数据
  • b、 get(adataset)=>如果adataset具有exist属性,则应对每个adataset执行请求,并填充有用的数组,该数组将在以后使用
  • c、 get(有用)=>应该触发并退出

  • 使用诸如
    switchMap
    mergeMap
    之类的映射功能将一个请求的结果映射到下一个请求。使用
    forkJoin
    同时执行多个请求

    因此,对于一对多方案,总体思路是:

    firstRequest().pipe(
    switchMap(results=>forkJoin(results.map(r=>nextRequest(r)))
    )
    
    对于您的情况,这将类似于:

    use=[];
    a、 获取('abc')。管道(
    switchMap(abcdatas=>forkJoin(getUseFulRequests(abcdatas)),
    轻触(有用=>有用的.forEach(u=>this.有用的.push(u)),
    switchMap(有用=>use.length?c.get('ghi'):空)
    ).订阅((吉达)=>{
    完整的。。。
    });
    函数getUseFulRequests(abcdatas:AbcData[]):Observable[]{
    返回abcdata。减少((acc,abcdata)=>{
    if(abcdata.exist){
    const request=b.get('def')管道(
    映射(defdatas=>defdatas.someval)
    )
    acc.push(请求);
    }
    返回acc;
    }, []);
    }
    

    如果
    getUseFulRequests(abcdatas)
    返回空数组或
    Use.length==0

    使用类似
    switchMap
    mergeMap
    的映射函数将一个请求的结果映射到下一个请求,则不会发出任何消息。使用
    forkJoin
    同时执行多个请求

    因此,对于一对多方案,总体思路是:

    firstRequest().pipe(
    switchMap(results=>forkJoin(results.map(r=>nextRequest(r)))
    )
    
    对于您的情况,这将类似于:

    use=[];
    a、 获取('abc')。管道(
    switchMap(abcdatas=>forkJoin(getUseFulRequests(abcdatas)),
    轻触(有用=>有用的.forEach(u=>this.有用的.push(u)),
    switchMap(有用=>use.length?c.get('ghi'):空)
    ).订阅((吉达)=>{
    完整的。。。
    });
    函数getUseFulRequests(abcdatas:AbcData[]):Observable[]{
    返回abcdata。减少((acc,abcdata)=>{
    if(abcdata.exist){
    const request=b.get('def')管道(
    映射(defdatas=>defdatas.someval)
    )
    acc.push(请求);
    }
    返回acc;
    }, []);
    }
    

    如果
    getUseFulRequests(abcdatas)
    返回空数组或
    use.length==0
    我认为处理此问题的最佳方法是使用高阶可观测值

    考虑下面的代码

    useful$ = a.get('abc').pipe(
      mergeMap(abcdatas => 
        abcdata.exist ? forkJoin(abcdatas.map(abcdata => b.get('def'))) : of(undefined)
      ),
      map(defdatas => defdatas.flat()),
      mergeMap(({ length }) => length ? c.get('ghi') : of(undefined))
    );
    
    useful$.subscribe({
      next: () => { 
        // Completed...
      }
    })
    
    我们首先通过管道传输
    a.get('abc')
    的结果,并使用mergeMap测试
    abcdata.exist
    。如果它确实退出,我们将返回
    forkJoin(abcdatas.map(abcdata=>b.get('def'))
    这将结合abcdatas上的map函数生成的观察值数组

    map(defdatas=>defdatas.flat()),
    将数组转换为单个数组 注意:在ES2019中引入了flat()


    接下来,我们将分解
    length
    属性,如果它存在,我们将返回最终的可观测值

    我相信处理这个问题的最佳方法是使用高阶可观测值

    考虑下面的代码

    useful$ = a.get('abc').pipe(
      mergeMap(abcdatas => 
        abcdata.exist ? forkJoin(abcdatas.map(abcdata => b.get('def'))) : of(undefined)
      ),
      map(defdatas => defdatas.flat()),
      mergeMap(({ length }) => length ? c.get('ghi') : of(undefined))
    );
    
    useful$.subscribe({
      next: () => { 
        // Completed...
      }
    })
    
    我们首先通过管道传输
    a.get('abc')
    的结果,并使用mergeMap测试
    abcdata.exist
    。如果它确实退出,我们将返回
    forkJoin(abcdatas.map(abcdata=>b.get('def'))
    这将结合abcdatas上的map函数生成的观察值数组

    map(defdatas=>defdatas.flat()),
    将数组转换为单个数组 注意:在ES2019中引入了flat()


    接下来,我们将分解
    length
    属性,如果它存在,我们将返回我们的最终可观测值

    ,我认为您要做的是:

    a.get("abc").pipe(
      mergeMap((abcdatas) => abcdatas.filter((abcdata) => abcdata.exist)), // let's create a stream with all those useful abcdata
      mergeMap(abcdata => b.get('def')), // and for each one of those we perform a b.get request
      toArray(), // once all the b.get requests have completed, emit a one value stream with an Array of those values values
      concatMap(useful => useful.length ? c.get('ghi') : EMPTY) // let's concat that result with the final request
    )
    

    我认为你想做的是:

    a.get("abc").pipe(
      mergeMap((abcdatas) => abcdatas.filter((abcdata) => abcdata.exist)), // let's create a stream with all those useful abcdata
      mergeMap(abcdata => b.get('def')), // and for each one of those we perform a b.get request
      toArray(), // once all the b.get requests have completed, emit a one value stream with an Array of those values values
      concatMap(useful => useful.length ? c.get('ghi') : EMPTY) // let's concat that result with the final request
    )
    

    感谢您的响应。有用的不仅仅是有用的请求,它是由第二次调用i形成的数组。b、 get()@MithunshreVatsa您可以使用
    点击
    从中间响应填充全局数组。例如,正如我所说的,我是新手,从axios和async出来需要时间,请等待并承诺谢谢,我从你的回答中学到了一些非常有用的东西,并给我打了一个明确的电话:)感谢你的回答。这不仅仅是对有用的请求,它是由第二次呼叫i形成的数组。b、 get()@MithunshreVatsa您可以使用
    点击
    从中间响应填充全局数组。例如,正如我所说的,我是新手,从axios和async出来需要时间,请等待并承诺谢谢,我从你的回答中学到了一些非常有用的东西,并给我打了一个明确的电话:)感谢你的回答