HTTP 拦截器未完成(即从未调用 Finalize)

Ron*_*nin 5 rxjs typescript angular-http-interceptors angular

在我的 Angular 8 项目中,我实现了最简单的方法HttpInterceptor,只传递请求,而不执行任何操作

\n\n

在我的 Angular 8 项目中,我实现了一个简单的方法HttpInterceptor,只需克隆原始请求并添加一个参数:

\n\n
@Injectable()\nexport class RequestHeadersInterceptor implements HttpInterceptor {\n\n  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\n    // original code return next.handle(request) // pass-by request as-is\n\n    return next.handle(request.clone({\n      params: request.params.set(\'language\', \'en\') }\n    ));\n  }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

在我的服务中,我有一个getFoos()方法可以进行 HTTP 调用,该调用将被以下内容拦截RequestHeadersInterceptor

\n\n
import { HttpClient } from \'@angular/common/http\';\nimport { Injectable } from \'@angular/core\';\nimport { finalize } from \'rxjs/operators\';\nimport { Foo } from \'.\';\n\n@Injectable({\n  providedIn: \'root\'\n})\nexport class FooService {\n  constructor(private http: HttpClient) { }\n\n  getFoos() {\n    return this.http.get<Foo[]>(\'/foos\')\n      .pipe(\n        finalize(() => console.log(\'observable completed!\'))\n      );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在我的组件中,我最终订阅了getFoos()

\n\n
fooService.getFoos().subscribe(console.log);\n
Run Code Online (Sandbox Code Playgroud)\n\n

预期输出

\n\n
[{ foo: 1\xe3\x80\x80}, { foo: 2 }]\nobservable completed!\n
Run Code Online (Sandbox Code Playgroud)\n\n

实际产量

\n\n
[{ foo: 1\xe3\x80\x80}, { foo: 2 }]\n
Run Code Online (Sandbox Code Playgroud)\n\n

如您所见,finalize永远不会触发。这是为什么?

\n\n

笔记

\n\n
    \n
  • 如果拦截器被删除,则会finalize触发,这是两种情况的预期行为
  • \n
  • 我如何向模块提供拦截器:
  • \n
\n\n
[{ foo: 1\xe3\x80\x80}, { foo: 2 }]\nobservable completed!\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  • 我更新了拦截器代码,因为我错误地指出,即使按原样传递请求,问题仍然存在。相反,它需要被克隆和改变。

  • \n
  • 我添加了一个演示,基于@PierreDuc 的演示(主要道具!)。但是,我无法在演示中重现该问题。这可能与某些请求或响应标头有关。

  • \n
\n\n

实时系统 API 上的响应标头

\n\n
Cache-Control: no-store, no-cache, must-revalidate, max-age=0 Cache-Control: post-check=0, pre-check=0\nCache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0\nConnection: keep-alive\nContent-Language: en-US\nContent-Length: 42\nContent-Type: application/json;charset=utf-8\nDate: Tue, 21 Jan 2020 15:44:33 GMT\nPragma: no-cache\nPragma: no-cache\nServer: nginx/1.16.1\nX-Content-Type-Options: nosniff\nX-Powered-By: Servlet/3.1\n
Run Code Online (Sandbox Code Playgroud)\n\n

实时系统 API 上的请求标头

\n\n
Accept: application/json, text/plain, */*\nAccept-Encoding: gzip, deflate, br\nAccept-Language: en-GB,en-US;q=0.9,en;q=0.8\nAuthorization: Basic xyzABC123\nCache-Control: no-cache\nConnection: keep-alive\nContent-Type: application/json\nCookie: check=true; anotherCookie=1; bla=2;\nHost: some.page.com:11001\nPragma: no-cache\nReferer: https://some.page.com\nSec-Fetch-Mode: cors\nSec-Fetch-Site: same-origin\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36\n
Run Code Online (Sandbox Code Playgroud)\n

Pie*_*Duc 2

“问题”是Connection: Keep-Alive标题。这会保持打开的连接

Connection 常规标头控制当前事务完成后网络连接是否保持打开状态。如果发送的值是保持活动的,则连接是持久的并且不会关闭,从而允许对同一服务器进行后续请求。

这将导致 Observable 未完成,直到连接终止。

所以这对你来说并不是真正的错误或问题。我猜你HttpInterceptor添加了这个标头,所以这就是只有在添加拦截器后才会导致的原因