为了账号安全,请及时绑定邮箱和手机立即绑定

使用 rxjs 以角度发送多个发布请求

使用 rxjs 以角度发送多个发布请求

智慧大石 2023-11-11 21:20:17
我有一个表单,我将姓名作为输入和计数(数字)。我想将号码附加到姓名上。例如。如果用户输入worker并计数5。我想附加从1开始直到计数即5的数字,它将类似于worker-1、worker-2、worker-3、worker-4、worker-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() 的部分,有更好的方法吗?
查看完整描述

3 回答

?
慕的地10843

TA贡献1785条经验 获得超8个赞

只需使用范围运算符,它接受两个参数;start & count( range(start: number, count: number): Observable) 并返回一个 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)

        })

      )

  }

}


查看完整回答
反对 回复 2023-11-11
?
墨色风雨

TA贡献1853条经验 获得超6个赞

生成是你的朋友:

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只会将您的前缀(例如“worker”)与要生成的数字连接起来bodyName。


...然后就取决于你了。从代码中尚不清楚您的 body 对象是什么样子,您想要对每个请求执行什么操作以及最终执行什么操作。


查看完整回答
反对 回复 2023-11-11
?
婷婷同学_

TA贡献1844条经验 获得超8个赞

尝试这个。例如 :


forkJoin([res1, res2, res3, res4, res5])

.pipe(map(data => data.reduce((result,arr)=>[...result,...arr],[])))

.subscribe(data =>{


  this.autoCompleteValues = data;

  console.log(this.autoCompleteValues);

});


查看完整回答
反对 回复 2023-11-11
?
qq_笑_17

TA贡献1818条经验 获得超7个赞

mergeMap将值转换为订阅的可观察量

mergeMap(value => observable) 将为您订阅并发出映射的可观察值的值。看起来您所需要的只是 mergeMap(body => service(body)) ,然后您就可以开始比赛了。


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


我不确定body您的示例中定义的位置,因此我假设它是一个具有某些属性的对象,并且您要向其添加另一个属性 ( 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将可观察数组转换为响应数组

可以做同样的事情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,...]). 它订阅每个可观察对象并等待它们全部完成。


不同之处在于 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)

  });

  

}


查看完整回答
反对 回复 2023-11-11
  • 3 回答
  • 0 关注
  • 130 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信