简体   繁体   English

在Angular App中在POST请求上使用switchMap进行Observable

[英]Using switchMap on POST Request for Observable in Angular App

In my Angular app I have a function that takes in a variety of user-selected filter values, and returns data accordingly. 在我的Angular应用程序中,我具有一个函数,该函数接受各种用户选择的过滤器值,并相应地返回数据。 These values are passed into the function via event emitters passing the values from one component to another, like so: 通过事件发射器将这些值从一个组件传递到另一个组件,将这些值传递到函数中,如下所示:

<data-list [records]="records"
    (sendLocation)="onFilterReceived($event, type = 'location')"
    (sendZipcode)="onFilterReceived($event, type = 'zipcode')"
    (sendFirstName)="onFilterReceived($event, type = 'firstName')"
    (sendLastName)="onFilterReceived($event, type = 'lastName')"
    (sendLanguage)="onFilterReceived($event, type = 'language')"
    (sendBranch)="onFilterReceived($event, type = 'branch')">
</data-list>

I then take in those values, process them, and then send out an POST request to the API to get the filtered data returned: 然后,我接受这些值,对其进行处理,然后向API发送POST请求以获取返回的过滤数据:

public onFilterReceived(value, type)
{
    let selections = this.filtersService.processByTypes(value, type);

    this.route.params.subscribe(
        (params: any) => {
            this.page = params['page'];
        }
    );

    let fn = resRecordsData => {
        this.records = resRecordsData;
        let data = resRecordsData.data;
    };

     this.filtersService.getByFilters(
        this.page - 1, this.pagesize, this.language = selections.language, this.location = selections.location,
        this.zipcode = selections.zipcode, this.firstName = selections.firstName, this.lastName = selections.lastName,
        this.branch = selections.branch, fn);
}

The filterService functions being called here look like this: 在此处调用的filterService函数如下所示:

filters = { language: [], location: [], zipcode: [], firstName: [], lastName: [], branch: [] };

public processByTypes(value, type) {
  if (value && type) { this.filters[type] = value; }
  return this.filters;
}

public getByFilters(page, pagesize, language?, location?, zipcode?, firstName?, lastName?, branch?, fn?: any) {
    return this.apiService.post({
      req: this.strReq, reqArgs: { page, pagesize, stage, language, location, zipcode, firstName, lastName, branch }, callback: fn });
}

And the API POST function being called here looks like this: 此处调用的API POST函数如下所示:

public post(params: {
    req: string,
    reqArgs?: any,
    reqBody?: any,
    callback?: IRequestCallback
}): Observable<Response>
{
    params['reqType'] = 'post';

    return this.runHttpRequest(params);
}

The problem I'm running into is that each time a filter value is received by the onFilterReceived() function it causes the POST request to fire, so I end up with 7 or 8 POST requests for basically unchanged filter values. 我遇到的问题是,每次onFilterReceived()函数接收到一个过滤器值时,都会触发POST请求,因此对于基本未更改的过滤器值,我最终会收到7或8个POST请求。 So what I want to do is gather those values and only make one POST request. 所以我想做的就是收集这些值,并且只发出一个 POST请求。

Right now the POST request returns an observable, so my thinking is that I should be able to use an operation like switchMap to handle this. 现在POST请求返回一个可观察到的消息,因此我的想法是我应该能够使用switchMap之类的操作来处理此问题。 Does this sound doable? 这听起来可行吗? That's question one. 这是第一个问题。 The second question is about getting the syntax right. 第二个问题是关于正确使用语法。

I tried chaining switchMap onto the end of the POST request like this: 我尝试将switchMap链接到POST请求的末尾,如下所示:

public getByFilters(page, pagesize, stage?, language?, location?, zipcode?, firstName?, lastName?, branch?, fn?: any) {
    return this.apiService.post({
      req: this.strReq, reqArgs: { page, pagesize, stage, language, location, zipcode, firstName, lastName, branch }, callback: fn }).switchMap;
}

... but that didn't work. ...但是那没有用。 No errors, but it didn't work, because I still see multiple POST requests going out. 没有错误,但是没有用,因为我仍然看到多个POST请求发出。

So am I understanding switchMap correctly? 我能正确理解switchMap吗? And what does the syntax need to look like if I want to chain it onto my POST request operation? 如果要将链链接到POST请求操作上,语法需要什么样?

I'll try to write a simplified example from which you hopefully get the idea. 我将尝试编写一个简化的示例,希望您能从中得到启发。 You should have a Subject of the current state of filters. 您应该具有过滤器当前状态的主题。 SwitchMap that to the api call and you can throw in debounceTime to give user time to make quick changes in succession. 将其切换到api调用,您可以投入debounceTime来给用户时间来快速进行连续更改。

Going to use the newer pipeable operators. 将使用较新的管道运算符。

filter$:Subject<any> = new Subject();
data:any;
destroy$:Subject<void> = new Subject();

ngOnInit() {
    this.filter$.pipe(
        takeUntil(destroy$), // stop and cleanup when component gone
        debounceTime(400),
        switchMap(filter => this.service.post(filter)) // switch one stream to another
    ).subscribe(data => this.data = data)
}

onFilterReceived(value, type)
{
    let selections = this.filtersService.processByTypes(value, type);
    this.filter$.next(selections);
}

ngOnDestroy() { this.destroy$.next() }

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

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