简体   繁体   English

如何处理Angular中forloop内取消的请求?

[英]How to handle the canceled request inside forloop in Angular.?

I have 5+ pages in my App.我的应用程序中有 5 个以上的页面。 I have the following method on header component.我在 header 组件上有以下方法。

The aim is, I need to show the status in the header if the user clicks the particular button.目的是,如果用户单击特定按钮,我需要在 header 中显示状态。 If I make a minimal or slow navigation between pages below code works fine.如果我在以下代码的页面之间进行最小或缓慢的导航,则可以正常工作。 But if I navigate pages very frequently, the request getting canceled, because in some other pages I am calling the different set of API's.但是如果我非常频繁地浏览页面,请求就会被取消,因为在其他一些页面中我正在调用不同的 API 集。

async geneStatus() {
    for (const x of Object.keys(this.gene)) {
    const operationId = this.gene[x]['name'];
    let operArr;
    try {
        operArr = await this.fetchEachStatus(name);
    } catch (err) {
        continue;
    }
    if (operArr[0] && operArr[0] === 'error') {
        continue;
    }
 // Doing my logics
}


fetchEachStatus(geneId): Promise<any[]> {
    return new Promise((resolve, reject) => {
    this.apiDataService.get(this.geneUrl+ '/' + geneId).subscribe(
        (res) => {
        setTimeout(() => {
            resolve(res);
        }, 500);
        }, err => {
        setTimeout(() => {
            resolve(['error']);
        }, 500);
        });
    });
}

Here the problem is if any one of the API gets cancelled the for loop is not iterating for the next elements.这里的问题是,如果 API 中的任何一个被取消,则 for 循环不会迭代下一个元素。 I need to iterate the loop if one API is get cancelled.如果一个 API 被取消,我需要迭代循环。 How can I fix this issue?我该如何解决这个问题? I am not sure where I am making the problem.我不确定我在哪里制造问题。

I see multiple issues.我看到了多个问题。 I think the conversion to observable to promise is not only unnecessary, but counter-productive.我认为将 observable 转换为 promise 不仅没有必要,而且会适得其反。 Using the observables directly would enable you to use RxJS functions and operators.直接使用 observables 将使您能够使用 RxJS 函数和运算符。 We can use the forkJoin function to make multiple simultaneous requests and catchError operator to mitigate the effects of potential errors.我们可以使用forkJoin function 发出多个同时请求和catchError运算符来减轻潜在错误的影响。

Try the following尝试以下

import { forkJoin } from 'rxjs';
import { catchError } from 'rxjs/operators';

geneStatus() {
  forkJoin(Object.keys(this.gene).map(gene => this.fetchEachStatus(gene['name']))).subscribe(
    res => {
      // res[0] - `{ success: true | false, geneId: geneId }` from `this.apiDataService.get(this.geneUrl + '/' + this.gene[0]['name'])`
      // res[1] - `{ success: true | false, geneId: geneId }` from `this.apiDataService.get(this.geneUrl + '/' + this.gene[1]['name'])`
      ...

      const passedGeneIds = res.filter(item => item.success).map(item => item.geneId);
      // passedGeneIds = [`geneId`, `geneId`, ...] - list of passed gene IDs

      const failedGeneIds = res.filter(item => !item.success).map(item => item.geneId);
      // failedGeneIds = [`geneId`, `geneId`, ...] - list of failed gene IDs

      // some other logic
    },
    error => {
      // essentially will never be hit since all the errors return a response instead
    }
  );
}

fetchEachStatus(geneId): Observable<any> {
  return this.apiDataService.get(this.geneUrl + '/' + geneId).pipe(
    map(_ => ({ sucess: true, geneId: geneId })),                  // <-- map to return the `geneId`
    catchError(error => of({ sucess: false, geneId: geneId }))     // <-- retun an observble from `catchError`
  );
}

Now you need to remember that each time a button is clicked multiple simultaeneous requests are triggered.现在您需要记住,每次单击按钮时都会触发多个同时请求。 One solution to overcome this issue is to cancel all current requests before triggering a new set of request.克服此问题的一种解决方案是在触发一组新请求之前取消所有当前请求。 For that you could bind the buttons to emit a central observable and trigger the requests using switchMap operator piped to that observable.为此,您可以绑定按钮以发出中央可观察对象并使用通过管道传输到该可观察对象的switchMap运算符触发请求。

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

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