【问题标题】:How to use ForkJoin for sequence of http requests Angular 4如何使用 ForkJoin 进行 http 请求序列 Angular 4
【发布时间】:2019-02-28 04:59:27
【问题描述】:

我有一个函数可以进行两次 http 调用,第二个 http 的输入取决于第一个 http 响应,我需要同时返回两个结果。我有以下引发错误的代码

SomeMethod(): Observable<any> {
    let firstResult;
    let secondResult;

    firstResult = http.get('////').map(data => {
        console.log('first response')
     secondResult = http.get('//// + {data.UserId}').map(response => {

        console.log('second response')
     })
    })

    return forkJoin([firstResult, secondResult]);
}

CallingMethod() {
    this.SomeMethod.subscribe(([firstResult, secondResult]) =>{
     /// Some logic
    })}

得到未定义的错误。期望一个 observable、promise 或数组。在调试知道第一个控制台输出正在打印后,第二个 http 调用从未进行过,也从未看到响应。

如何使用 forkJoin 或任何其他机制一起返回两个嵌套调用响应?

【问题讨论】:

    标签: angular angular4-httpclient


    【解决方案1】:

    Here is a StackBlitz 了解如何使用concatMap 执行此操作。 concatMap 将顺序执行,而forkJoin 将并行执行。

    你需要知道的

        const requests = [
          this.http.get('https://jsonplaceholder.typicode.com/todos/1'),
          this.http.get('https://jsonplaceholder.typicode.com/todos/2'),
          this.http.get('https://jsonplaceholder.typicode.com/todos/3'),
          this.http.get('https://jsonplaceholder.typicode.com/todos/4'),
          this.http.get('https://jsonplaceholder.typicode.com/todos/5'),
          this.http.get('https://jsonplaceholder.typicode.com/todos/6')
        ];
    
    
        from(requests).pipe(    
          concatMap((request) => request.pipe(delay(2200)))
        ).subscribe((res) => {
          this.results$.next(this.results$.getValue().concat(res))
        })
    
    1. 我们创建了一个请求数组(它们是可观察的)。
    2. 使用 from 运算符获取您的数组并发出每个数组项
    3. 使用concatMap 使这些排放变平

    我在这里也添加了一个延迟来模拟慢速加载。

    【讨论】:

    • 您有什么建议如何修改您的代码,以便在所有顺序(!)请求完成后获得 once 的结果(就像 forkJoin 所做的那样)?
    • Arg,无法再编辑。如果其他人正在搜索这种行为,就像这样:from(requests).pipe( concatMap((request) =&gt; request.pipe(delay(2200))), reduce((acc, cur) =&gt; [...acc, cur], []), ).subscribe((res) =&gt; { console.log('res', res); })
    • @juli 我认为toArray() 也可以代替reduce
    【解决方案2】:

    使用 Async & await 来控制多个 http 请求。

    async SomeMethod(): Promise <any> {
    
        let firstResult;
        let secondResult;
        firstResult = await http.get('////').toPromise();
        secondResult = await http.get('//// + {res1.UserId}').toPromise();
    
        return forkJoin(firstResult, secondResult);
    }
    
     CallingMethod() {
        this.SomeMethod().then(result => {
           /// Some logic
        });
     }
    

    【讨论】:

    • 触摸我的朋友
    【解决方案3】:

    以下代码应该可以工作:

    SomeMethod(): Observable < any > {
      let firstResult;
      let secondResult;
    
      return http.get('////').pipe(
        switchMap(res1 => http.get('//// + {res1.UserId}').pipe(
          map(res2 => [res1, res2])
        ))
      );
    }
    
    CallingMethod() {
      this.SomeMethod().subscribe(([firstResult, secondResult]) => {
        /// Some logic
      })
    }
    

    【讨论】:

    • 在使用代码后出现以下错误void 类型的 this 上下文不可分配给 observable 类型的 this 方法 甚至点击链接 rxjs pipe 但 coudn'解决
    • 您需要发布完整代码才能正确调试。我认为这只是某个地方的一些愚蠢的小错误。
    【解决方案4】:

    forkJoin 采用内联参数,而不是作为数组(除非 rxjs 在最新版本和 Angular v4 中捆绑的内容之间发生了变化)

    const req1 = this.http.get('https://jsonplaceholder.typicode.com/todos/1');
    const req2 = this.http.get('https://jsonplaceholder.typicode.com/todos/2');
    
    const results = forkJoin(req1, req2)
    

    输出:

    [
      {
        "userId": 1,
        "id": 1,
        "title": "delectus aut autem",
        "completed": false
      },
      {
        "userId": 1,
        "id": 2,
        "title": "quis ut nam facilis et officia qui",
        "completed": false
      }
    ]
    

    StackBlitz 在 v6 中,但如果需要,它很容易回溯。

    【讨论】:

      猜你喜欢
      • 2019-01-20
      • 1970-01-01
      • 1970-01-01
      • 2018-03-30
      • 2017-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多