关于javascript:关于-Angular-HTTP-Interceptor-中-Request-和-Response-的-immutable-特性

4次阅读

共计 1367 个字符,预计需要花费 4 分钟才能阅读完成。

只管拦截器可能批改申请和响应,但 HttpRequest 和 HttpResponse 实例属性为 readonly,这意味着其具备 immutability 个性。

这种个性是 Angular 框架无意为之的设计:应用程序可能会在一个 HTTP 申请胜利实现之前,多次重试申请。换言之,这意味着 Interceptor chain 能够屡次重新处理 (re-process) 雷同的申请。如果拦截器能够批改原始申请对象,则重试操作将从批改后的申请开始,而不是从原始申请开始,这会给应用程序的解决引入极大的不确定性。

因而,Angular Interceptor 解决上下文中的 HTTP 申请和响应的 immutability 个性,确保拦截器在每次尝试中解决的是雷同的申请。

TypeScript 阻止开发人员设置 HttpRequest 对象中具备 readonly 的属性,看个具体的例子:

// Typescript disallows the following assignment because req.url is readonly
req.url = req.url.replace('http://', 'https://');

如果应用程序里必须更改 HTTP Request,请先克隆它并批改克隆,而后再将其传递给 next.handle()。能够在一个步骤中克隆和批改申请,如以下示例所示:

// clone request and replace 'http://' with 'https://' at the same time
const secureReq = req.clone({url: req.url.replace('http://', 'https://')
});
// send the cloned, "secure" request to the next handler.
return next.handle(secureReq);

上面是 SAP Spartacus Interceptor 中应用 clone 办法去批改一个 HTTP Request 的具体例子:

[图片]

TypeScript 的 readonly 属性,并不能阻止 Request body 字段被 deep update.

下列代码能工作,然而却是一个蹩脚的设计,起因如前所述:如果该 Interceptor 被反复调用,则每次调用会在前一次调用批改的 HTTP Request 的根底上再次进行批改,一直造成 Side Effect:

req.body.name = req.body.name.trim(); // bad idea!

Angular 举荐的做法顺次是:

  • 对 Request body 进行 copy,并批改 copy 版本
  • 应用 HTTP Request 的 clone 办法,克隆申请对象。
  • 用批改后的 body copy 版本,替换克隆进去的 HTTP 申请的 body 字段。

伪代码如下:

// copy the body and trim whitespace from the name property
const newBody = {...body, name: body.name.trim() };
// clone request and set its body
const newReq = req.clone({body: newBody});
// send the cloned request to the next handler.
return next.handle(newReq);
正文完
 0