【问题标题】:How to send request sequently with checks before each request?如何在每个请求之前通过检查顺序发送请求?
【发布时间】:2018-11-16 10:05:47
【问题描述】:

我需要:

  • 依次发送 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

所以我想要的是在对象无效时不发送请求。并且我想从最初的 observable 处理 next id,前提是对先前的处理结束。所以我想要这样的流程:

  1. 第一个 id 上的 map + concatMap
  2. 第二个 id 上的 map + concatMap
  3. 还有更多更多更多...

我只通过扩展 concatMap 代码来处理这个问题。是否有可能在concatMap 之前将此检查提取到另一个可管道操作员?所以concatMap body 会更简单。

我尝试了 mergeMap 运算符,例如:

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

我在控制台中得到了这个:

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

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

我认为我误解了这一点。 from(this.ids) 无论如何都会发出值。它不会等待 concatMap 或 map 或任何其他运算符。在那一刻,当from(this.ids) 中发出新值时(它将在concatMap 完成之前)它会处理整个链:map + concatMap。我需要的是在concatMap 完成第一个处理之后,以某种方式说 rxjs 来处理第二个发出的值。然后它应该在 concatMap 处理完第二个 e t c 之后处理第三个发出的值。

这里有一个扩展的例子: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

如何更改我的 observable,使其如下所示:

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

【问题讨论】:

  • 也许我不明白你想做什么,但你可以直接返回 throwError 而不是 empty()concatMap 将继续下一个项目。创建错误通知将释放链。
  • 对不起,可能是我的错。我编辑了一些问题。当 observable 因错误完成时就可以了。这就是我需要的。请检查我已编辑问题的结尾部分。
  • 这是我需要的:stackblitz.com/edit/angular-zjsuvu。有什么办法可以简化吗?

标签: angular rxjs httpclient concatmap


【解决方案1】:

对于初学者,我认为您误解了错误处理在 rxjs 中的工作原理。您作为第二个参数传递给订阅函数的错误处理函数永远不会被多次调用。一旦一个 observable 遇到一个错误,它就完成并且不再起作用。所以你不能使用那个函数来捕获多个错误。

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,而是返回一个对象,该对象指示请求是否已执行,如果已执行,则返回响应。

【讨论】:

  • Once an observable encounters one single error, it is completed and no longer functions 这就是我需要的。如果发现任何错误,我不需要处理队列。
  • 我将此添加到我需要的内容中。另外,我会更多地编辑问题。请检查我已编辑问题的结尾部分。
  • 这是我需要的:stackblitz.com/edit/angular-zjsuvu。有什么办法可以简化吗?
  • 好吧,对于初学者,您可以用一个过滤器运算符替换这 2 个 mergeMaps
  • 是的。还有什么改进吗?
猜你喜欢
  • 2010-12-10
  • 1970-01-01
  • 2018-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多