【问题标题】:multiple http.post in AngularAngular中的多个http.post
【发布时间】:2020-08-04 17:43:06
【问题描述】:

我正在尝试为数组的每个元素发送一个 http.post 请求,我的方法运行良好,但是当我订阅时,它会为每个请求执行此操作,如果有人可以帮助我优化这个,我会非常感谢,这里我留下我的代码的 sn-ps。

组件.ts

saveExclusion() {
this.indForm.value.Centers.forEach(element => {
  for (const days of this.exclusionDays) {
    delete days.horadesde;
    delete days.horahasta;
    delete days.id;
    for (const key in days) {
      if (days[key] === true) {
        days[key] = true;
      }else if (days[key] === false) {
        delete days[key];
      }
    }
  }
  const valueForm = this.indForm.value;
  valueForm.ResourceId = this.idResource;
  valueForm.TimeZoneId = 'America/Santiago';
  valueForm.CenterId = element;
  this.exclusionFunc = false;
  this.apiFca.saveNew(valueForm, this.exclusionDays)
    .pipe(last()).subscribe((res: any) => {
      console.log(res)
      if (res === '200') {
        this.successMessage = true;
        this.exclusionDays = [];
        this.indForm.reset();
        this.ngOnInit();
        setTimeout(() => {
          this.successMessage = false;
        }, 3000);
      }
    }, err => {
      console.log('error', err);
    });
});

}

service.ts

saveNew(exclusionData, daysBlock) {
  let reason = '';
  const dt = new Date();
  const n = dt.getTimezoneOffset();
  const tz = new Date(n * 1000).toISOString().substr(14, 5);
  if (exclusionData.OtherReason) {
    reason = exclusionData.ExclusionReason + ' ' + exclusionData.OtherReason;
  } else {
    reason = exclusionData.ExclusionReason;
  }
  if (exclusionData.ExclusionType !== 'Partial' ) {
    daysBlock = [];
  }
  const data = {Exclusion: new ExclusionClass(
   [],
   reason,
   exclusionData.ExclusionType,
   exclusionData.Repetition,
   exclusionData.CenterId,
   exclusionData.ProfessionalName,
   exclusionData.ResourceId,
   daysBlock,
   exclusionData.TimeZoneId,
   'Exclude',
   exclusionData.Unit,
   exclusionData.ValidFrom + 'T' + exclusionData.ValidTimeFrom + ':00-' + tz,
   exclusionData.ValidTo + 'T' + exclusionData.ValidTimeUntil + ':59.999-' + tz
  )};
  if (exclusionData.CenterId === '') {
    delete data.Exclusion.CenterId;
  }
  return this.http
      .post("url", data)
      .pipe(
        map((res: any) => {
          return res.code;
        })
      );
}

您好,我期待您的 cmets,谢谢。

【问题讨论】:

标签: javascript angular rxjs httpclient


【解决方案1】:

我对我的 rxjs 知识并不完全有信心,但看起来,因为.pipe(last()),你只看最后一个请求?我建议您仅在全部完成且没有错误的情况下设置成功,例如

this.apiFca.saveNew(valueForm, this.exclusionDelays)
    .subscribe(
        res => {
            console.log(res);
        },
        err => {
            console.log(err);
        },
        () => {
            this.successMessage = true;
            // etc. etc. etc.
        });

或者也许不是使用this.successMessage,而是使用this.saveState$ 之类的东西,这将是一个使用saveExclusion() 函数管理的'idle'(或其一些枚举)初始化的BehaviorSubject 对象。这样,saveExclusion() 函数的开头就可以

  1. 设置const saveState$ = this.saveState$
  2. 断言saveState$.getValue() === 'in process' 或者如果不是,请采取措施,
  3. saveState$.next('in process');

您可以将订阅行更改为

this.apiFca.saveNew(valueForm, this.exclusionDelays)
.subscribe(
    res => {
        if (res !== '200') {
            saveState$.next('unexpected result')
    }   },
    err => {
        console.log(err);
        saveState$.next('error');
    },
    () => {
        if (saveState$.getValue() === 'in process') {
            saveState$.next('success');
    }   }
);

然后你也可以订阅你的组件的saveState$(尽管在你想要提供saveState$.asObservable()的组件之外,所以值不能被外部代码注入)。这在您的组件初始化中提供了一些优雅的事件驱动代码:

saveState$.pipe(filter(val => val === 'error'))
.subscribe(functionToTellYourUserThereWasAnError);

// if successful, we want other code to know, but immediately change it back to 'idle' even if other code errors
saveState$.pipe(filter(val => val === 'success')
.subscribe(val => saveState$.next('idle'));

// upon success, reset me
saveState$.pipe(filter(val => val === 'success'))
.subscribe(
    val => {
        this.exclusionDays = [];
        // etc. etc.
        // setTimeout not needed because set to 'idle' in a different thread.
    }
)

另外,我认为您的模板也可以反映和更改 UI 以响应 saveState$ 中的更改,因此可以根据 saveState 是否为“空闲”等启用/禁用您的保存按钮。

【讨论】:

  • 我一直在思考这个问题! this.apiFca.saveNew(valueForm, this.exclusionDelays).subscribe(... 可能会改进吗? this.apiFca.saveNew(valueForm, this.exclusionDelays).pipe(map(res => res.code), every(code => code === 200), takeUntil(saveState$)) 将发出一个成功/失败布尔值,如果 saveState$ 被其他东西更改,则中止。只是一个想法。保留或折腾。
  • 另外,read this。我认为我们都不够优雅,在这里。如果该服务返回一个观察者,并且该组件将事物连接起来,以便一个可观察的保存请求执行mapTo 服务所需的任何内容,然后订阅该服务,这不是更好吗?一个订阅组件的生命周期而不是每个保存请求一个?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
  • 1970-01-01
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多