【问题标题】:Any Scenario(s) that RXJS Observable Subscribe wont trigger either success and errorRXJS 可观察订阅的任何场景都不会触发成功和错误
【发布时间】:2021-12-20 23:31:56
【问题描述】:

这更像是问题而不是解决问题。
我想知道是否有任何“成功”和“错误”都没有被触发的场景。

"/logout"的post调用会产生Http状态返回码200 预期的响应主体为空

import { httpClient } from angular/common/http;
private http: HttpClient;

this.http.post<any>('/logout', {})
      .subscribe(
      () => {
        console.log("Logout");
      }, error => {
        console.log(error);
      },
      () => {
        console.log("Finally");
      });

它将在 100% 的时间内输出“终于”。这意味着根本不会触发成功和错误。

是否存在成功和错误都不会触发的可能性。很明显,http 状态码响应是 200 OK。

更新: @meriton 提供的答案非常有用。

【问题讨论】:

  • 无论状态如何,都会触发成功或错误。如果服务器没有响应,浏览器将超时请求(也是一个错误)
  • 但它不会触发成功或错误,这让我感到困惑。
  • @Drenai 很抱歉。我的坏

标签: javascript angular rxjs rxjs-observables


【解决方案1】:
  1. http 库的成功取决于 Status:200,它不需要 message.body 存在

  2. 使用RXJS管道流的示例代码,您可以通过捕获成功和错误,控制超时来控制流。它还演示了如何将 .subscribe() 方法用作经典的 finally

RXJS 流程示例:

 this.http
      .post<any>('/logout',{})
      .pipe(
        map(() => {                 // OK
          return { success: true, err: null }; 
        }),
        timeout(10000),             // CONTROL TIMEOUT
        catchError((e) => {         // IN CASE OF ERROR
          return of({success: false, err:e});
        })
      )
      .subscribe((result) => {        // FINALLY here
        if (result.success) {
          console.log('Logged out successfully');
        } else {
          console.log('Logout failed', result.err); 
        }
      });

【讨论】:

  • 你能给我们解释一下你的代码是做什么的以及它如何属于这个问题吗?
  • 这个问题不是 100% 清楚的。通过问题中的摘要:“它不会触发任何一个“成功”调用(因为没有数据返回)?并且不会触发错误。 Zeo 显然担心不会触发成功,因为他认为 HTTP 没有 Body 响应就等于成功没有被触发。他的问题也在 RXJS 下提出。这段代码为他提供了一个与经典订阅(成功、错误、最终)匹配到 RXJS 流的精确流。它也清楚地展示了即使是空的身体也能捕捉到成功。加上使用 subscribe() 来替代“finally”
  • 您的示例使用的是get,问题是关于post 的响应正文为空
  • 更新到post,方法一样
【解决方案2】:

Observable,一般情况下不需要填写或报错。它们可能永远存在,并继续发出值。

但是,HttpClient 返回的Observable 保证根据 HTTP 状态以成功或错误终止(尽管在超时的情况下错误可能需要几分钟)响应。没有身体的存在不会影响这一点。如果请求成功,observable 将发出一个值:响应正文(如果响应正文不存在,则为 null)。

我无法重现您关于“根本不会触发成功或错误”的说法。您可能误解了回调的含义吗?当您提供三个回调订阅时,它们按顺序排列:

  • next 回调,它接收发出的值
  • error 回调,通知 Observable 由于错误而中止
  • complete 回调,通知Observable 已成功完成

混淆回调的危险是 RXJS 团队让 deprecated 将多个回调作为单独的参数传递给 RXJS 8 订阅的原因之一。编写代码的未来证明方法是:

this.http.post<any>('/logout', {}).subscribe({
  complete: () => {
    console.log("Logout successful")
  },
  error: (error) => {
    console.log(error);
  }
});

顺便说一句,这些回调都不是“终于”的意思,就像在try-statement 的finally 子句中一样,它在成功和错误的情况下都会执行。如果您想做某事而不管Observable 是成功完成还是因错误而失败,您可以使用finalize 运算符。

【讨论】:

  • 这是不正确的。 OP 有三个回调,并没有说它们没有被调用,而是询问是否有任何情况下它们不会被调用。 'finally' 文本只是输出到控制台,但它仍然是 complete 回调
  • @Drenai 答案清楚地描述了 HttpClient 返回的 Observable 的预期:“但是,HttpClient 返回的 Observable 保证以成功或错误终止(尽管错误可能需要根据响应的 HTTP 状态,在超时的情况下等待几分钟。没有正文的存在不会影响这一点。”关于原因和更好的方法,还有更多细节。 IMO 这个答案是正确的。
  • @Drenai:感谢您指出这一点。当他说没有调用回调时,我相信 OP,并且 Observable 在没有主体的情况下跳过发射似乎是最合乎逻辑的解释,但在这种情况下 Observable 发射 null 是正确的。我已编辑以解决此问题。我也改写了我对“终于”的评论,现在更清楚了吗?我只是想确保 OP 理解 complete 仅在 成功 完成的情况下被调用,而不是在异常终止的情况下被调用,因为 OP 将完成记录为“终于”确实具有误导性。跨度>
猜你喜欢
  • 2018-03-19
  • 2021-06-17
  • 1970-01-01
  • 2017-04-13
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多