如何在每个请求之前依次发送请求和支票?

时间:2018-11-16 10:05:48

标签: angular rxjs httpclient concatmap

我需要:

  • 随后发送N个请求(我使用concatMap做到这一点)
  • 仅当对象有效时(我使用验证代码扩展concat映射)
  • 在第一个错误时停止队列(通过服务器错误响应或通过客户端检查拒绝)

现在代码如下:

ids = [{valid: true, id: 1}, {valid: true, id: 2}, {valid: true, id: 3}, {valid: false, id: 4}]
constructor(httpClient: HttpClient) {
  from(this.ids)
  .pipe(
    map(obj => ({...obj, id: obj.id + 5})),
    concatMap(obj => {
      console.log('concat map');
      if (obj.valid === false) {
        return throwError('not valid');
      } else {
        return httpClient.get(`https://jsonplaceholder.typicode.com/todos/${obj.id}`);
      }
    })
  )
  .subscribe(
    result => console.log('success', result),
    result => console.log('error', result),
    () => console.log('complete')
  );
}

这里是堆叠闪电战:https://stackblitz.com/edit/angular-5vwbjg

所以我想要的是如果对象无效则不发送请求。而且我想从初始可观察到的next id进行处理,仅当对前一个的处理结束时。所以我想要像这样的流

  1. 第一个ID上的map + concatMap
  2. 第二个ID上的map + concatMap
  3. 更多更多...

我仅通过扩展concatMap代码来处理此问题。是否可以在concatMap之前以某种方式将此检查提取到另一个可管道运算符?这样concatMap的主体会更简单。

我尝试了像这样的mergeMap运算符:

mergeMap(obj => {
  console.log(obj);
  if (obj.valid === false) {
    return throwError('not valid');
  } else {
    return of(obj);
  }
}),

我在控制台中得到了这个

enter image description here

这不是正确的结果。我期望3个请求,然后1个错误。 预期结果:

enter image description here

在我的情况下,也许还有更漂亮的方式来描述检查功能?有任何想法吗?没有带有两个分支的if

我认为我误解了这一点。 from(this.ids)始终会发出值。它不会等待concatMap或地图或任何其他运算符。在那一刻,当在from(this.ids)中发出新值时(将在concatMap之前),它处理整个链:map + concatMap。我需要的是在concatMap处理完第一个后,说出rxjs处理第二个发射值。然后concatMap处理完第二步等后,它应该处理第三步发射的值。

此处是一个扩展的示例:https://stackblitz.com/edit/angular-ovffm4?file=src/app/app.component.ts

在这里,我有2个客户端检查和1个服务器响应。

这是我在控制台中看到的内容:

map
first check true
second check 6
make request
map
first check true
second check 7
map
first check true
second check 8
map
first check true
second check 9
map
first check true
second check 10
map
first check false
success {userId: 1, id: 6, title: "qui ullam ratione quibusdam voluptatem quia omnis", completed: false}
make request
success {userId: 1, id: 7, title: "illo expedita consequatur quia in", completed: false}
complete

如何更改我的观测值,就像这样:

map
first check true
second check 6
make request
success {userId: 1, id: 6, title: "qui ullam ratione quibusdam voluptatem quia omnis", completed: false}
map
first check true
second check 7
make request
success {userId: 1, id: 7, title: "illo expedita consequatur quia in", completed: false}
map
first check true
second check 8
map
first check true
second check 9
map
first check true
second check 10
map
first check false
complete

1 个答案:

答案 0 :(得分:0)

对于初学者来说,我认为您误解了rxjs中错误处理的工作方式。您作为第二个参数传递给订阅函数的错误处理函数将永远不会被调用超过一次。一旦可观察对象遇到一个错误,它就会完成,并且不再起作用。因此,您不能使用该功能捕获多个错误。

http://reactivex.io/documentation/operators/subscribe.html

一个Observable调用此方法以指示它未能生成预期的数据或遇到其他错误。 这将停止Observable,并且不会进一步调用onNext或onCompleted。 onError方法将指示错误原因的参数作为其参数(有时是诸如Exception或Throwable之类的对象,有时是简单字符串,具体取决于实现方式。)

您将永远无法以这种方式处理它。

这可能是另一种方式:

https://stackblitz.com/edit/angular-wbu3tv

摘要:

  concatMap(obj => {
    console.log(obj);
    if (obj.valid === false) {
      return of({
          response: null,
          success: false
        });
    } else {
      return httpClient.get(`https://jsonplaceholder.typicode.com/todos/${obj.id}`).pipe(map(response => {
        return {
          response: response,
          success: true
        }
      }));
    }
  })

因此,基本上,我不使用throwError,而是返回一个对象,该对象指示是否已执行请求以及响应(如果已执行)。