繁体   English   中英

使用 rxjs 在 angular 中发送多个 post 请求

[英]Send multiple post request in angular using rxjs

我有一个表格,我将名字作为输入和计数(数字)。

我想把 append 这个号码给名字。 例如。

如果用户输入工人并计数 5。我想 append 从 1 到计数即 5 的数字,它将像工人 1、工人 2、工人 3、工人 4、工人 5。

然后我想向服务器发送多个请求以将这些工作人员添加到数据库中。

我目前正在做这样的事情。

addItems() {

    for (let i = 1; i <= this.count; i++) {
        body.name = this.createItemForm.get('name').value + '-' + i;
        this.add(body);
      }

 }

add(body: formBody) {
    this.cvmService.createServer(body).subscribe(() => {
      this.alertify.success('New item was successfully created');
      this.close(true);
    }, error => {
      this.alertify.error('\n' + error);
    });
  }

我的问题是如何使用 rxjs 做到这一点,这是最好的操作员。 特别是我在 for 循环中调用 add() 的部分,有更好的方法吗?

generate是你的朋友:

const baseName = this.createItemForm.get('name').value + '-';

generate(1, x => x <= this.count, x => ++x).pipe(
  map(val => baseName + val),
).subscribe(bodyName => {
 // do something with your worker-1 .... worker-count
});

generate将生成从 1 到您的输入计数的序列。

map只会将您的前缀(例如“工人”)与生成的数字连接bodyName

......然后由你决定。 从代码中不清楚你的身体 object 是什么样的,你想对每个请求执行什么操作以及最终执行什么操作。

只需使用范围运算符,它接受两个参数; start & count ( range(start: number, count: number): Observable ) 并返回一个 Observable ,它发出一个数字序列,您可以根据需要对其进行转换。

考虑以下示例:

interface Body {
  name: string
}

class Component {
  constructor(
    private alertify: Alertify,
    private cvmService: CvmService
  ) { }

  public addMany(count: number, base: string): void {
    return range(1, count).pipe(

     /**
      * transform each emitted number into a @Body
      */

      map(number => { 
        const body: Body = { name: `${base}${number}` };
        return body;
      }),

      toArray(), // <-- collect emitted values

     /**
      * transform the array of @Body[] returned by @toArray() into an 
      * array of Observables and use @forkJoik operator to wait for all
      * Observables to complete
      */

      switchMap(array => forkJoin(array.map(body => this.addOne(body))))
    ).subscribe(() => console.log("done!"))
  }


  /**
  * transform each body into an Observable 
  * without subscribing to it
  * use @tap operator to listen for events that will be raised
  * by future subscriptions
  */

  public addOne(body: Body): Observable<void> {
    return this.cvmService.createServer(body)
      .pipe(
        tap({
          next: () => this.alertify.success('New item was successfully created'),
          error: error => this.alertify.error('\n' + error)
        })
      )
  }
}

尝试这个。 例如:

forkJoin([res1, res2, res3, res4, res5])
.pipe(map(data => data.reduce((result,arr)=>[...result,...arr],[])))
.subscribe(data =>{

  this.autoCompleteValues = data;
  console.log(this.autoCompleteValues);
});

mergeMap将值转换为订阅的 Observables

mergeMap(value => observable) 将为您订阅并发出映射的 observable 的值。 看起来您只需要 mergeMap(body => service(body)) 就可以参加比赛了。


以下是您使用 RxJS 所做的非常直接的翻译。 如果您的代码有效,那么(理论上,我无法测试它)这个或非常类似的东西应该可以工作。

我不确定body在您的示例中定义的位置,所以我假设它是一个具有一些属性的 object 并且您正在向它添加另一个属性( name

addItems(){
  
  range(1, this.count).pipe(
    map(i => ({
      ...body,
      name: `${this.createItemForm.get('name').value}-${i}`
    })),
    mergeMap(body => this.cvmService.createServer(body))
  ).subscribe({
    next: resp => {
      this.alertify.success('New item was successfully created');
      this.close(true);
    },
    error: err => this.alertify.error('\n' + err),
    complete: () => console.log(`${this.count} items where succesfully created`)
  });
  
}

forkJoin将 Observable 数组转换为响应数组

使用forkJoin可以完成同样的事情,因为看起来您的服务调用发出一次并完成。

在这里,您首先需要创建所需的服务调用数组。 我通过将数组[1,2,3,4,5]映射到主体对象[{name:worker-1},{name:worker-2},{name:worker-3},{name:worker-4},{name:worker-5}]然后将主体对象映射到服务调用[observable,observable,observable,observable,observable]

所有这一切都是在没有任何 RxJS 的情况下完成的,RxJS 部分是forkJoin([observable,observable,...]) 它订阅每个 observables 并等待它们全部完成。

不同之处在于 forkJoin 会将最终结果作为数组发出。 如果您仍然希望为每个结果发出警报并调用 this.close(true),那么我们需要检测每个服务调用(数组中的可观察源)来执行此操作。

当您订阅时, next回调将获得一个数组。 实现如下所示:

addItems(){
  
  forkJoin(
    Array.from(
      {length: this.count}, 
      (_,i) => i+1
    ).map(i => ({
      ...body,
      name: `${this.createItemForm.get('name').value}-${i}`
    })).map(body => 
      this.cvmService.createServer(body).pipe(
        tap(_ => {
          this.alertify.success('New item was successfully created');
          this.close(true);
        })
      )
    )
  ).subscribe({
    next: resp => {
      console.log(`${resp.length} items where succesfully created`);
    },
    error: err => this.alertify.error('\n' + err)
  });
  
}

暂无
暂无

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

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