使用rxjs Angular和ngrx同步处理Observable以防止太多HTTP请求超时

使用rxjs Angular和ngrx同步处理Observable以防止太多HTTP请求超时,angular,rxjs,observable,rxjs5,ngrx,Angular,Rxjs,Observable,Rxjs5,Ngrx,我有以下代码。它获取一个患者数组并构建一个rows对象this.rows,我在angular 4组件前端的一个表中显示(我也在使用rxjs 5.5) 我的问题是每行的hasAlert属性都是通过调用hasAlerts()来分配的。在HasAlerts方法中,我通过this.dataService.fetchItems()为每个患者发出http请求 当有许多患者时,太多的HTTP请求将异步发生,并且它们将从HasAlerts()开始失败(超时)。是否有方法限制这一点,或者从HasAlerts()一

我有以下代码。它获取一个患者数组并构建一个rows对象
this.rows
,我在angular 4组件前端的一个表中显示(我也在使用rxjs 5.5)

我的问题是每行的hasAlert属性都是通过调用hasAlerts()来分配的。在HasAlerts方法中,我通过
this.dataService.fetchItems(
)为每个患者发出http请求

当有许多患者时,太多的HTTP请求将异步发生,并且它们将从HasAlerts()开始失败(超时)。是否有方法限制这一点,或者从HasAlerts()一次处理一个可观察到的请求?

下面是解决这个问题的可能方法

  • 我认为concatMap可能会有帮助,但我不确定如何使用它。还应该使用它来处理每个患者/行,或者尝试将每个hasAlert()观察值聚合到一个列表中,然后尝试使用concatMap一次处理一个
  • 一个解决方法是我添加了注释//的patientsAlertsProcessed变量包装器,用于限制hasAlertsMethod。我将其限制为只点击该方法15次,以避免超时问题。这并不理想,因为这15个异步请求完成后,我无法再次启动它
  • 代码如下

    ngOnInit(): void {
        this.store.dispatch(new patients.Load([]));
    
        this.patients$ = this.store.select(fromPatients.getAll); 
        var patientsAlertsProcessed =0;
        this.patients$.debounceTime(2000).map(p =>{//Emits Observable<Patient[]>s, the debounceTime is to take the last one as it builds up
          this.rows = p.map(pat => {// p = Patient[], iterate through the array of patients
            var observations=0;
            var rowX= {
              username: pat.username,
              id: pat.id,
              hasAlert:false, 
            };
    
            if (patientsAlertsProcessed<15){// this is done to throttle the HasAlerts Method
              this.hasAlerts(pat).do(x => {
                observations++;
                if (observations>0)
                {
                  rowX.hasAlert=true;
                }
              }).subscribe();
              patientsAlertsProcessed++;
            }
            return rowX;
          });
        }).subscribe(
           ()=> { },
           ()=> {
            this.table.recalculatePages();
          }
        );
    
      }
      hasAlerts(pat: Patient): Observable<Observation> {
        var obs$= this.dataService.fetchItems<Observation>(// this is making an HTTP get request 
            "Observation",
            null,
            pat.id
          ).filter(function (x){
            if (x.category.coding[0].code == "GlucoseEvent"){ 
                return true;
            }
            else{
              return false; 
            }
          }
        );
        return obs$;
      }
    
    ngOnInit():void{
    this.store.dispatch(新患者.Load([]);
    this.patients$=this.store.select(fromPatients.getAll);
    var patientsAlertsProcessed=0;
    this.patients$.debounceTime(2000).map(p=>{//)发出可见光,debounceTime将在其建立时取最后一个
    this.rows=p.map(pat=>{//p=Patient[],遍历患者数组
    var观测值=0;
    变量rowX={
    用户名:pat.username,
    id:pat.id,
    hasAlert:错,
    };
    如果(患者)已处理{
    观察++;
    如果(观测值>0)
    {
    rowX.hasAlert=true;
    }
    }).subscribe();
    patientsAlertsProcessed++;
    }
    返回rowX;
    });
    }).订阅(
    ()=> { },
    ()=> {
    this.table.recomparePages();
    }
    );
    }
    hasAlerts(pat:患者):可观察到{
    var obs$=this.dataService.fetchItems(//这是在发出HTTP get请求
    “观察”,
    无效的
    身份证
    ).过滤器(功能(x){
    如果(x.category.coding[0].code==“GlucoseEvent”){
    返回true;
    }
    否则{
    返回false;
    }
    }
    );
    返回obs$;
    }
    
    您可能想尝试一下这些方法

    const concurrency = 10; 
    const rowsWithAlerts = [];
    
    this.patients$.debounceTime(2000)
    .switchMap(patients => Observable.from(patients)) // patients is of type Patient[]
    .mergeMap(patient => {
       rowsWithAlerts.push(patient);
       this.hasAlerts(patient).do(
       hasAlertsResult => {
         // here you have hold to both the patient and the result of
         // hasAlerts call
         patient.hasAlerts = hasAlertsResult;
       }}), concurrency)
    .subscribe(
       () => this.rows = rowsWithAlerts;
    )
    
    这里的关键是使用
    mergeMap
    操作符,将并发级别设置为一个值,在本例中为10,但显然可以是任何值


    这允许限制您同时订阅的可观察对象的数量,在您的情况下,这意味着限制您进行的http调用的数量。

    尝试一下,我注意到您对rxjs很精通。当您熟悉rxjs时,有没有什么资源对您有帮助?我设置此的逻辑。我会在在ListCMAP行中的“=”之后,我不建议这样做。你必须考虑,<>代码>患者< /COD>数组,你得到的参数是SwitcMax,是一个与你的代码不同的数组。在您的示例中,要将用户名ID和警报作为属性分配给rowX?也可以在开关映射行中进行观察。从(p)p未定义您是对的,它不应该是p,而应该是
    switchMap
    中的患者。我还更新了我的答案,以便您为每个患者设置
    hasAlerts
    标志,并将每个患者推入行数组。