首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Angular 9订阅内部订阅

Angular 9订阅内部订阅
EN

Stack Overflow用户
提问于 2020-06-21 22:23:18
回答 2查看 1.5K关注 0票数 1

我正在使用Angular 9和rxjs 6,并尝试获取节点列表:

NodeService.ts

public getList(): Observable<Nodes[]> { return this.http.get<Nodes[]>(URL); }

节点实体:

代码语言:javascript
复制
export class Nodes {
     public id: number;
     public name: string;
     public site_id: number;
     public site: Site;
}

nodes.component.ts:

代码语言:javascript
复制
public getAllNodes() {
  this.dataSource.data = [];
  this.nodeService.getList()
    .subscribe(
      nodes => {
        nodes.map(
          (node) => {
            this.siteService.getSiteById(node.site_id).subscribe(site => {
              node.site = site;
            })
          });
        this.dataSource.data = nodes;
        console.log(nodes);
      },
      error => {
        console.log(error);
      },
      () => {
      }
    );
}

默认情况下,node.site = =>,所以我使用node.site_id在subscribe方法中获取完整的"Site“对象。但是我有将近6000次"siteService.getSiteById()“调用,并且我遇到了类似这样的错误:资源不足。

你有没有更好的办法,

谢谢

EN

回答 2

Stack Overflow用户

发布于 2020-06-21 23:20:13

如果您需要进行6000个单独的HTTP调用,您可能需要修改后端以在单个请求中返回所有信息。同时,您可以尝试使用带有fromof函数的concatMap的RxJS switchMap operator来按顺序执行请求。

代码语言:javascript
复制
import { of, from } from 'rxjs';
import { switchMap, concatMap, finalize } from 'rxjs/operators';

public getAllNodes() {
  this.dataSource.data = [];
  let sites = [];
  this.nodeService.getList().pipe(
    switchMap(nodes => {
      let requests = [];
      this.dataSource.data = nodes;
      nodes.forEach(node => requests.push(this.siteService.getSiteById(node.site_id)));
      return from(requests);
    }),
    concatMap(request => of(request)),
    finalize(() => {
      this.dataSource.data.forEach((node, index) => node.site = sites[index]);
    })
  ).subscribe(
    site => {
      sites.push(site);
    },
    error => {
      // handle error
    }
  );
}

现在6000个请求将按顺序完成,所以它太慢了。

更新:使用mergeMap的并发请求

正如Will Alexander在评论中所建议的,您可以使用RxJS mergeMap operator来实现并发请求。但我建议您将其保持在6以下,因为大多数浏览器对对唯一域的并发请求数量有硬性限制。

这样你就可以替换

代码语言:javascript
复制
concatMap(request => of(request))

使用

代码语言:javascript
复制
mergeMap(request => of(request), null, 5)   // <-- 5 concurrent requests
票数 0
EN

Stack Overflow用户

发布于 2020-06-22 21:31:54

大致是这样的:

代码语言:javascript
复制
public getAllNodes() {
  return this.nodeService.getList().pipe(

    // emit all elements of the array separately
    map(nodes => from(nodes)),
    
    // subscribe to each Observable in turn
    // allow 5 concurrent requests
    mergeMap(node$ => node$, null, 5).pipe(

      // for each node, get the corresponding site, and emit the full object
      concatMap(
        node => this.siteService.getSiteById(node.site_id),
        (node, site) => { ...node, site })
    ),

    // when Observable completes, emit all emissions as an Array
    toArray()
  );
}

更新:考虑到getList()返回可观测对象的事实

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62499871

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档