Angular 角度10 forkJoin取消请求

Angular 角度10 forkJoin取消请求,angular,rxjs,Angular,Rxjs,这应该是一个简单的一个角专业有。 我有一个简单的方法: private addMultiple(products: Product[]): void { let observables: Observable<Product>[] = []; products.forEach((product: Product) => observables.push(this.productService.create(product))); forkJoin(o

这应该是一个简单的一个角专业有。 我有一个简单的方法:

private addMultiple(products: Product[]): void {
    let observables: Observable<Product>[] = [];

    products.forEach((product: Product) => observables.push(this.productService.create(product)));

    forkJoin(observables).subscribe();
}
private addMultiple(产品:Product[]):void{
let可观测项:可观测[]=[];
products.forEach((product:product)=>observables.push(this.productService.create(product));
forkJoin(observates.subscribe();
}
如果我向该方法发送一个产品,它可以正常工作,但是如果我尝试多次(100次),我只会收到大量取消的请求,我不知道为什么

有人知道我是否应该使用不同的方法吗


这是我的产品服务

import { Inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { finalize, map } from 'rxjs/operators';
import { BehaviorSubject, Observable } from 'rxjs';

import { Product, Attempt, RequestOptions } from '../models';
import { HttpServiceConfig, HTTP_SERVICE_CONFIG } from '../configs';

@Injectable({
providedIn: 'root',
})
export class ProductService {
    private endpoint: string = 'products';

    public items: BehaviorSubject<Product[]>;
    public loading: BehaviorSubject<boolean>;

    constructor(
        @Inject(HTTP_SERVICE_CONFIG) public config: HttpServiceConfig,
        private httpClient: HttpClient
    ) {
        this.items = new BehaviorSubject<Product[]>([]);
        this.loading = new BehaviorSubject<boolean>(false);
    }

    list(categoryId: number, options?: RequestOptions): Observable<Product[]> {
        this.loading.next(true);
        return this.httpClient
        .get<Attempt<Product[]>>(
            `${this.config.apiUrl}/categories/${categoryId}/${this.endpoint}/master`,
            options?.getRequestOptions()
        )
        .pipe(
            map((response: Attempt<Product[]>) => {
            if (response.failure) return response.result;
            this.items.next(response.result);
            return response.result;
            }),
            finalize(() => this.loading.next(false))
        );
    }

    get(id: number, slug: string, options?: RequestOptions): Observable<Product> {
        return this.httpClient
        .get<Attempt<Product>>(
            `${this.config.apiUrl}/${this.endpoint}/${id}?slug=${slug}`,
            options?.getRequestOptions()
        )
        .pipe(
            map((response: Attempt<Product>) => {
            return response.result;
            })
        );
    }

    public create(item: Product, options?: RequestOptions): Observable<Product> {
        return this.httpClient
        .post<Attempt<Product>>(
            `${this.config.apiUrl}/${this.endpoint}`,
            item,
            options?.getRequestOptions()
        )
        .pipe(
            map((response: Attempt<Product>) => {
            if (response.failure) return response.result;
            const newItem = response.result;
            const items = this.items.value;
            items.push(newItem);
            this.items.next(items);
            return response.result;
            })
        );
    }

    public updateSpecification(
        item: Product,
        options?: RequestOptions
    ): Observable<Product> {
        return this.httpClient
        .put<Attempt<Product>>(
            `${this.config.apiUrl}/${this.endpoint}/specification`,
            item,
            options?.getRequestOptions()
        )
        .pipe(
            map((response: Attempt<Product>) => {
            if (response.failure) return response.result;
            const newItem = response.result;
            const items = this.items.value;
            this.remove(items, newItem.id);
            items.push(newItem);
            this.items.next(items);
            return response.result;
            })
        );
    }

    public approve(item: Product, options?: RequestOptions): Observable<Product> {
        return this.httpClient
        .put<Attempt<Product>>(
            `${this.config.apiUrl}/${this.endpoint}/approve`,
            item,
            options?.getRequestOptions()
        )
        .pipe(
            map((response: Attempt<Product>) => {
            if (response.failure) return response.result;
            const newItem = response.result;
            const items = this.items.value;
            this.remove(items, newItem.id);
            items.push(newItem);
            this.items.next(items);
            return response.result;
            })
        );
    }

    public reject(item: Product, options?: RequestOptions): Observable<Product> {
        return this.httpClient
        .put<Attempt<Product>>(
            `${this.config.apiUrl}/${this.endpoint}/reject`,
            item,
            options?.getRequestOptions()
        )
        .pipe(
            map((response: Attempt<Product>) => {
            if (response.failure) return response.result;
            const newItem = response.result;
            const items = this.items.value;
            this.remove(items, newItem.id);
            items.push(newItem);
            this.items.next(items);
            return response.result;
            })
        );
    }

    private remove(items: Product[], id: number | string) {
        items.forEach((item, i) => {
        if (item.id !== id) {
            return;
        }
        items.splice(i, 1);
        });
    }
}
从'@angular/core'导入{Inject,Injectable};
从'@angular/common/http'导入{HttpClient};
从“rxjs/operators”导入{finalize,map};
从“rxjs”导入{BehaviorSubject,Observable};
从“../models”导入{Product,trust,RequestOptions};
从“../configs”导入{HttpServiceConfig,HTTP_SERVICE_CONFIG};
@注射的({
providedIn:'根',
})
出口类产品服务{
私有端点:字符串='products';
公共项目:行为主体;
公共加载:行为主体;
建造师(
@注入(HTTP_服务_配置)公共配置:HttpServiceConfig,
私有httpClient:httpClient
) {
this.items=新行为主体([]);
this.loading=新行为主体(false);
}
列表(类别ID:编号,选项?:请求选项):可观察{
this.loading.next(true);
返回此.httpClient
.得到(
`${this.config.apiUrl}/categories/${categoryId}/${this.endpoint}/master`,
选项?.getRequestOptions()
)
.烟斗(
映射((响应:尝试)=>{
if(response.failure)返回response.result;
this.items.next(response.result);
返回响应结果;
}),
完成(()=>this.loading.next(false))
);
}
get(id:number,slug:string,options?:RequestOptions):可观察{
返回此.httpClient
.得到(
`${this.config.apiUrl}/${this.endpoint}/${id}?slug=${slug}`,
选项?.getRequestOptions()
)
.烟斗(
映射((响应:尝试)=>{
返回响应结果;
})
);
}
公共创建(项目:产品,选项?:请求选项):可观察{
返回此.httpClient
.邮政(
`${this.config.apiUrl}/${this.endpoint}`,
项目,,
选项?.getRequestOptions()
)
.烟斗(
映射((响应:尝试)=>{
if(response.failure)返回response.result;
const newItem=response.result;
const items=this.items.value;
items.push(newItem);
本.项.下(项);
返回响应结果;
})
);
}
公共专业化(
项目:产品,,
选项?:请求选项
):可见{
返回此.httpClient
.放(
`${this.config.apiUrl}/${this.endpoint}/specification`,
项目,,
选项?.getRequestOptions()
)
.烟斗(
映射((响应:尝试)=>{
if(response.failure)返回response.result;
const newItem=response.result;
const items=this.items.value;
删除(items,newItem.id);
items.push(newItem);
本.项.下(项);
返回响应结果;
})
);
}
公共批准(项目:产品、选项?:请求选项):可观察{
返回此.httpClient
.放(
`${this.config.apiUrl}/${this.endpoint}/approve`,
项目,,
选项?.getRequestOptions()
)
.烟斗(
映射((响应:尝试)=>{
if(response.failure)返回response.result;
const newItem=response.result;
const items=this.items.value;
删除(items,newItem.id);
items.push(newItem);
本.项.下(项);
返回响应结果;
})
);
}
公共拒绝(项目:产品、选项?:请求选项):可观察{
返回此.httpClient
.放(
`${this.config.apiUrl}/${this.endpoint}/reject`,
项目,,
选项?.getRequestOptions()
)
.烟斗(
映射((响应:尝试)=>{
if(response.failure)返回response.result;
const newItem=response.result;
const items=this.items.value;
删除(items,newItem.id);
items.push(newItem);
本.项.下(项);
返回响应结果;
})
);
}
私有删除(项目:产品[],id:编号|字符串){
items.forEach((item,i)=>{
如果(item.id!==id){
返回;
}
项目.拼接(i,1);
});
}
}

如果服务器在几乎同一时间被太多请求击中,则可能会取消请求,这就是使用具有100个可观察对象的
forkJoin
所发生的情况

forkJoin
并行启动所有可观察对象的“执行”

如果要控制并行执行的数量,应使用
concurrency
参数集尝试
mergeMap
。如果您希望将请求与响应匹配,这种方法可能会稍微复杂一些

代码可能是这样的

//设置要并发飞行的请求数
const并发=10;
//使用from从一系列产品中生成可观察的
来自(产品)管道(
//使用mergeMap执行请求
mergeMap(product=>this.productService.create(product.pipe)(
//返回一个对象,该对象包含结果和生成的产品