Angular Rxjs 多个并行 HTTP 请求/调用阻塞导航 - 优先取消队列并发
Angular Rxjs Multiple Parallel HTTP Requests / Calls blocking navigation - Priority Cancel Queue Concurrent
我知道有类似的线程,但没有一个可以为我的问题提供合适的解决方案。
Pre: 我同时在服务器端和客户端导航。这意味着在前端使用 routerLink 进行的每次导航和调用的任何路由都伴随着对服务器的 HTTP 请求调用。
情况:我正在打开一个对话框以显示用于创建 position
的表单。为此 position
我需要显示我从 API 加载的 elements
列表。对于每个 element
,我需要加载一个额外的 thumbnail
。所以我需要一个 API 调用来获取 86 个 elements
,然后需要 86 个请求来获取 thumbnail
。我将这些元素保存在服务中以防止再次加载它们。因此,我在加载它们之前检查是否已经有 elements
。 API 调用在我打开对话框时启动。
getElementsWithThumbnails() {
if (this.elementsSource.value.length === 0) {
this.apiService.getElements().subscribe(
(next) => {
this.elementsSource.next(next);
this.elementsSource.value.forEach((epl, index) => {
const format = 'JPG';
this.apiService.getThumbnail(epl.id, format, '400', '400', 'true').subscribe(
(blob) => {
epl.thumbnail = blob;
}
);
});
}
);
}
}
缩略图请求方法:
getThumbnail(
elementId: string, format: string, width: string,
height: string, sameratio: string
): Observable<SafeUrl> {
return this.httpClient.get(
this.apiUrl +
`/elements/${elementId}/thumbnail?format=${format}&width=${width}&height=${height}&sameratio=${sameratio}`
, {
responseType: 'blob'
}).pipe(
map(res => {
return this.blobToSanitizedUrl(res);
})
);
}
问题:如果用户决定取消表单并想要导航 forward/backward - 他不能,因为 navigation request
在队列的末尾。
是否有任何方法可以将 thumbnail
调用的优先级设置为较低的调用以在较小的负载上处理?
提前致谢。
问题是浏览器对同一端点的并行请求有限制。 api 是否与前端同源?如果不是,则限制可能会更低。
我的看法:
为缩略图使用 url。我假设您将它们显示在某些 img
标签中。为什么不设置 href
并让浏览器处理图像的加载。继续这个想法,您可以使用 "inview" 指令来延迟图像的加载,直到它们实际可见(这也取决于业务和要求)。
将并行请求限制为 getThumbnail
。您可以这样做(使用 mergeMap 的 concurrent
参数):
const format = 'JPG';
this.apiService.getElements()
.pipe(
switchMap(items => {
this.elementsSource.next(items);
return from(items);
}),
mergeMap(item => {
return this.apiService
.getThumbnail(item.id, format, '400', '400', 'true')
.pipe(
tap(blob => item.thumbnail = blob)
)
}, 2) // max 2 requests in parallel
)
.subscribe();
我知道有类似的线程,但没有一个可以为我的问题提供合适的解决方案。
Pre: 我同时在服务器端和客户端导航。这意味着在前端使用 routerLink 进行的每次导航和调用的任何路由都伴随着对服务器的 HTTP 请求调用。
情况:我正在打开一个对话框以显示用于创建 position
的表单。为此 position
我需要显示我从 API 加载的 elements
列表。对于每个 element
,我需要加载一个额外的 thumbnail
。所以我需要一个 API 调用来获取 86 个 elements
,然后需要 86 个请求来获取 thumbnail
。我将这些元素保存在服务中以防止再次加载它们。因此,我在加载它们之前检查是否已经有 elements
。 API 调用在我打开对话框时启动。
getElementsWithThumbnails() {
if (this.elementsSource.value.length === 0) {
this.apiService.getElements().subscribe(
(next) => {
this.elementsSource.next(next);
this.elementsSource.value.forEach((epl, index) => {
const format = 'JPG';
this.apiService.getThumbnail(epl.id, format, '400', '400', 'true').subscribe(
(blob) => {
epl.thumbnail = blob;
}
);
});
}
);
}
}
缩略图请求方法:
getThumbnail(
elementId: string, format: string, width: string,
height: string, sameratio: string
): Observable<SafeUrl> {
return this.httpClient.get(
this.apiUrl +
`/elements/${elementId}/thumbnail?format=${format}&width=${width}&height=${height}&sameratio=${sameratio}`
, {
responseType: 'blob'
}).pipe(
map(res => {
return this.blobToSanitizedUrl(res);
})
);
}
问题:如果用户决定取消表单并想要导航 forward/backward - 他不能,因为 navigation request
在队列的末尾。
是否有任何方法可以将 thumbnail
调用的优先级设置为较低的调用以在较小的负载上处理?
提前致谢。
问题是浏览器对同一端点的并行请求有限制。 api 是否与前端同源?如果不是,则限制可能会更低。
我的看法:
为缩略图使用 url。我假设您将它们显示在某些
img
标签中。为什么不设置href
并让浏览器处理图像的加载。继续这个想法,您可以使用 "inview" 指令来延迟图像的加载,直到它们实际可见(这也取决于业务和要求)。将并行请求限制为
getThumbnail
。您可以这样做(使用 mergeMap 的concurrent
参数):
const format = 'JPG';
this.apiService.getElements()
.pipe(
switchMap(items => {
this.elementsSource.next(items);
return from(items);
}),
mergeMap(item => {
return this.apiService
.getThumbnail(item.id, format, '400', '400', 'true')
.pipe(
tap(blob => item.thumbnail = blob)
)
}, 2) // max 2 requests in parallel
)
.subscribe();