【问题标题】:Angular 7 Wait for http network call to finish before triggering next oneAngular 7在触发下一个之前等待http网络调用完成
【发布时间】:2020-01-08 15:39:18
【问题描述】:

我有一个数据服务,它会在其他服务需要时定期触发 http 调用。现在,此服务异步工作,因此可能会在前一个尚未完成时请求数据服务触发 http 调用。

我想知道当我需要进行 http 呼叫时,如何使用 rxjs 检查是否有正在进行的呼叫

数据服务:

constructor(private http: HttpClient){}

// if this gets called while another hasn't returned, wait for it and then trigger the next http call
public request(method, url, options): Observable<any>{
    return this.http.request(method, url, options);
}

服务 A:

public syncA(){
    setTimeout(() => {
       this.dataService.request('GET', 'someUrl', someOptions).subscribe((response) => {
        console.log('periodic call returns ', response});
    }, 45000);
}

服务 B:

public doB(): Observable<any>{
 return this.dataService.request('GET', 'someUrl', someOptions)
}

这种情况是服务 B 调用 doB 而 syncA 已触发请求但尚未完成。

【问题讨论】:

  • 显而易见的答案是从第一个请求的subscribe 回调中使用第二个请求。这不适用于您的用例吗?
  • @TheHeadRush 你能提供一个样本来说明这将如何?示例被简化,在实际应用中它们可能是多个服务,在不同的时刻触发 https 调用,有的每隔一定时间触发一次,有的由用户明确决定
  • 确实,A 和 B 只是对他们拨打的电话感兴趣,他们不需要知道其他正在处理数据服务的事情,这个应该处理他们等待的请求在触发下一个之前完成...如果他们听取所有响应,他们将收到他们不感兴趣的信息,当其他服务从其他服务完成时

标签: angular typescript rxjs rxjs-observables


【解决方案1】:

执行此操作的 rxjs 方法是使用 concatMapTo

正如stackblitz example 所示

const fakeRequest = of('Network request complete').pipe(delay(3000));
//wait for first to complete before next is subscribed
const example = sampleInterval.pipe(concatMapTo(fakeRequest));
//result
//output: Network request complete...3s...Network request complete'
const subscribe = example.subscribe(val => console.log(val));

【讨论】:

    【解决方案2】:

    您可以使用 behaviorSubject 来存储加载道具并仅在它为 false 时才释放管道,如下所示:

    private loading = new BehaviouSubject<boolean>(false);
    
    constructor(private http: HttpClient){}
    
    // if this gets called while another hasn't returned, wait for it and then trigger the next http call
    public request(method, url, options): Observable<any>{
        return this.loading.pipe(
            filter(value => value === false),
            take(1),
            tap(() => this.loading.next(true)),
            mergeMap(() => this.http.request(method, url, options)),
            tap(() => this.loading.next(false))
        );
    }
    

    【讨论】:

    • 这似乎是实现它的方法,尽管我仍然可以看到在某些情况下调用多个请求而不等待前一个正在运行的请求完成。考虑例如我有一个调用 public doInServiceC(){ return forkJoin([ this.ds.request(m1,u1,o1), this.ds.request(m2,u2,o2), this.ds 的服务的情况.request(m3,u3,o3), ... ]).map(() => { return })} 如果是这种情况,我发现通过解决方案,所有这些请求都会被完全调用
    • 所以您需要一些请求等待全部完成,而其他请求可以随时请求?
    • 我需要每个请求等待前一个请求完成,不管它的 1 是在另一个被调用时出现还是 20 是同时出现并且应该排队等待一次调用一个,直到没有人离开......如果在清除这个请求队列的同时,更多的人也应该排队
    • 也许不是使用布尔类型变量来存储加载,您可以存储一个整数,对您发出的每个请求进行计数,当它得到结果时,它会递减计数器......我会明天尝试更新此代码。
    • uhmm...想多了,也许一个简单的计数器是行不通的。我猜你需要像队列列表这样的东西来放置这些请求并在它被弹出时继续管道......
    猜你喜欢
    • 2022-12-03
    • 1970-01-01
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    相关资源
    最近更新 更多