[英]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
将值转换为订阅的 ObservablesmergeMap(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.