简体   繁体   English

用 Observable 替换 Angular 响应式表单中的 setTimeout()

[英]Replacing a setTimeout() in an Angular Reactive Form with an Observable

I want to replace a setTimout() with an Observable in an Angular reactive form.我想用 Angular 反应形式的 Observable 替换 setTimout()。

I have a grandchild component that serves a section of a larger reactive form, receives an array of data objects from an API endpoint, packs that data into a Form Array, and submits it to the form.我有一个孙子组件,它服务于较大的响应式表单的一部分,从 API 端点接收数据对象数组,将该数据打包到表单数组中,然后将其提交给表单。 This works well.这很好用。

The problem is that the asynchronous nature of our API endpoints causes the form data of this grandchild component to render old data before the new data can initialize itself and clear out the old data and repopulate the new data.问题是我们的 API 端点的异步特性导致这个孙子组件的表单数据在新数据可以自行初始化并清除旧数据并重新填充新数据之前呈现旧数据。 We've solved this with a setTimout() of 500 ms.我们用 500 毫秒的 setTimout() 解决了这个问题。 It works well on the front end.它在前端运行良好。

The problem is that the setTimeout() is causing issues with our e2e testing failing because it completes the test before the data is loaded.问题是 setTimeout() 导致我们的 e2e 测试失败,因为它在加载数据之前完成了测试。 Plus, a timeout is not a long term solution to this async issue... especially if the data could occasionally take longer than 1/2 second (not a usual case, but definitely plausible).另外,超时并不是这个异步问题的长期解决方案......特别是如果数据有时可能需要超过 1/2 秒(不是常见情况,但绝对是合理的)。

I'm hoping to replace my timeout with an observable as a better solution that won't block our tests and can handle async much more safely.我希望用一个 observable 代替我的超时作为一个更好的解决方案,它不会阻止我们的测试并且可以更安全地处理异步。 Problem is that I cannot get the observable to work and I'm still an RxJS novice.问题是我无法让 observable 工作,而且我仍然是 RxJS 新手。

Here is the original function with the timeout that is currently running:这是当前正在运行的具有超时的原始函数:

setTimeout(() => {
      this.dataRow = [];
      for (let item of this.data.row) {
        this.dataRow.push(item);
      }
    }, 500);

Here is my attempt to recreate with an Observable:这是我用 Observable 重新创建的尝试:

this.dataRow = [];
   this.dataEmitter = from(this.data.row).pipe(delay(1000)).subscribe(data => this.dataRow.push(data);)

My code creates a data stream, but doesn't seem to work the same as the timeout.我的代码创建了一个数据流,但似乎与超时不同。 How can I accomplish this?我怎样才能做到这一点? Is this even the correct way to approach this problem?这甚至是解决这个问题的正确方法吗?

EDIT:编辑:

this.dataEmitter = of(this.data.row).pipe(delay(1000)).subscribe(row => {
  for (let item of row) {
    this.dataRow.push(item);
  }
}

delay(1000) delays by 1 sec. delay(1000)延迟 1 秒。 for every emit.每次发射。 And your snippet is not correct - you can't push(row) because row is undefined (as seen in the snippet).而且您的代码段不正确 - 您不能push(row)因为row undefined (如代码段所示)。

so if this.data.row is an Object, you need to make it iterable (like an array) if you want to emit this.data.row in "peaces".因此,如果this.data.row是一个对象,如果您想在“和平”中发出this.data.row ,则需要使其可迭代(如数组)。

But if you just want to get rid of setTimeout :但是,如果您只想摆脱setTimeout

this.dataEmitter = from([this.data.row]).pipe(delay(1000)).subscribe(row => {
  for (let item of row) {
    this.dataRow.push(item);
  }
}

Your code would be like this:您的代码将是这样的:

this.dataRow = []

of(this.data.row)
 .pipe(delay(500))
 .subscribe(data => {
   for(let item of data) {
     this.dataRow.push(item);
   }
 }) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM