如何在 Angular 2 中取消 HTTPRequest?

Posted

技术标签:

【中文标题】如何在 Angular 2 中取消 HTTPRequest?【英文标题】:How to cancel a HTTPRequest in Angular 2? 【发布时间】:2016-07-29 04:55:30 【问题描述】:

我只知道如何拒绝请求承诺。

return new Promise((resolve, reject) => 
    this.currentLoading.set(url, resolve, reject);

    this.http.get(url, headers: reqHeaders)
        .subscribe(
            (res) => 
                res = res.json();

                this.currentLoading.delete(url);
                this.cache.set(url, res);

                resolve(res);
            
        );
);

【问题讨论】:

【参考方案1】:

您可以拨打unsubscribe

let sub = this.http.get(url, headers: reqHeaders)
            .subscribe(
                (res) => 
                    res = res.json();

                    this.currentLoading.delete(url);
                    this.cache.set(url, res);

                    resolve(res);
                
            );

sub.unsubscribe();

更多信息在这里:http://www.syntaxsuccess.com/viewarticle/angular-2.0-and-http

【讨论】:

此答案在 beta.15 中不再有效。现在 Observable 中没有 unsubscribe 方法。 unsubscribe 已替换为 dispose 我正在使用 Angular2 的 RC.5,并且存在 unsubscribe(rxjs 版本 5.0.0-beta.6)。也许它在制造 cmets 后就恢复了?不确定差异来自哪里。 @DawsonToth Angular 2 团队很久没有更新 rxjs,会在 RC6 中更新 什么是退订突然停止取消请求?可能是什么问题?【参考方案2】:

您可以使用以下简单的解决方案:

if ( this.subscription ) 
   this.subscription.unsubscribe();

this.subscription = this.http.get( 'awesomeApi' )
 .subscribe((res)=> 
  // your awesome code..
)

【讨论】:

适用于 Angular 2.4.6 - 这应该是公认的答案 是否可以通过.toPromise()方法和then(),catch()完成? @SaeedNamati 为什么需要通过 promise 完成? this.subscription 的类型是什么?? this.subscription 的错字是 Subscription from rxJs。我会将第一行更正为if ( this.subscription && !this.subscription.closed ) ,以检查它是否已被取消订阅【参考方案3】:

聚会有点晚了,但这是我的看法:

import  Injectable  from '@angular/core'
import  Http  from '@angular/http'
import  Observable  from 'rxjs/Observable'
import  Subscriber  from 'rxjs/Subscriber'

@Injectable ()
export class SomeHttpServiceService 
  private subscriber: Subscriber<any>
  constructor(private http: Http) 

  public cancelableRequest() 
    let o = new Observable(obs => subscriber = obs)
    return this.http.get('someurl').takeUntil(o)
      .toPromise() //I dont like observables
      .then(res => 
        o.unsubscribe
        return res
      )
  
  public cancelRequest() 
    subscriber.error('whatever')
  

这允许您手动取消请求。有时我最终会得到一个可观察的或承诺,它会对页面上的结果进行更改。如果请求是自动启动的(用户没有在 x 毫秒的字段中输入任何内容)能够中止请求是很好的(用户突然再次输入内容)...

takeUntil 也应该使用简单的超时 (Observable.timer) 如果这是您正在寻找的 https://www.learnrxjs.io/operators/filtering/takeuntil.html

【讨论】:

为什么你不喜欢 observables?对于http来说和promise一样,但是也有error和complete @Mick,我认为 clearfix 只是在满足 OP 对承诺的偏好,而不是表达他/她的意见。 #theSpiritOf***【参考方案4】:

您可以在 observable 上使用 SwitchMap,这将取消任何先前请求的响应,并且只请求最新的:

https://www.learnrxjs.io/operators/transformation/switchmap.html

【讨论】:

怎么样?能给我们举个例子吗? 这里的例子:angular-2-training-book.rangle.io/handout/http/…【参考方案5】:

使用switchMap[docs],这将取消所有正在进行的请求并仅使用最新的。

get(endpoint: string): Observable<any> 
        const headers: Observable<url: string, headers: HttpHeaders> = this.getConfig();
        return headers.pipe(
            switchMap(obj => this.http.get(`$obj.url$endpoint`,  headers: obj.headers, params: params ) ),
            shareReplay(1)
        );
    

shareReplay 将为任何迟到的订阅者发出最新的值。

【讨论】:

如果您的headers 没有任何可观察的链接,该怎么办。我在单击按钮时进行了 http 调用,但从文档中,我只能在 observable 上使用 switchMap【参考方案6】:

这是一个很棒的主题,我还有更多信息要提供。我有一个可能会持续很长时间的 API 调用。所以我需要前一个请求以超时取消。我今天才发现我可以在管道函数中添加一个timeout 运算符。一旦超时完成其计数,这将取消之前的 HTTP 请求。

示例...

return this.exampleHttpRequest()
  .pipe(
    timeout(3000),
    catchError(err => console.log(error)
)

【讨论】:

以上是关于如何在 Angular 2 中取消 HTTPRequest?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 4+ 中取消/取消订阅所有挂起的 HTTP 请求

如何在拦截器中取消当前请求 - Angular 4

在Angular中取消或关闭模式后如何不更新数据?

Angular 2 动态表单 - 实现取消功能

如何取消订阅由 Angular 服务创建的 observable [重复]

Angular 2:由于表单未连接而取消表单提交