Angular中不使用.subscribe回调的http.post

31

我想知道是否可以只进行HTTP POST请求,而无需订阅回调函数,就像这样:

 this._http.post('/list/items/update?itemId=' + itemId + "&done=" + done, null);

不要这样做

 this._http.post('/list/items/update?itemId=' + itemId + "&done=" + done, null)
        .subscribe();
5个回答

23

我认为你不能做到。

http.post(以及get, put, delete等)返回一个冷的Observable,即一个Observable,其特点是:

在订阅期间创建并激活其基础生产者。

参考资料

这意味着由Observable表示的函数仅通过subscribe()方法激活。

方便的方法也会订阅,有关Observable#toPromise()的实现细节,请参见此处


那个问题应该被删除或者扩展,因为目前它是具有误导性的。正如2oppin在下面所示,你实际上是可以做到的,所以说“我不认为你能够做到”这种说法是错误的。 - Sasuke Uchiha
@Sasuke Uchiha 我认为 toPromise 实际上是在 它的实现 中订阅了 Observable。 - Picci
那是一个非常好的发现。可以请你将它添加到你的答案中吗? - Sasuke Uchiha

12

我正在使用 Promise 转换(需要 rxjs):

import 'rxjs/add/operator/toPromise';
@Injectable()
export class SomeService {
....
  post(sp: Seatplace, date?: Date) : Promise<any> {
     return this.http.post(
       '/list/items/update?itemId=' + itemId + "&done=" + done, 
        null
     ).toPromise();
  }
}

9

我曾经有同样的疑问,但后来我发现其实我并不在乎是否有人订阅了这个可观察对象。我只是想无论如何都发送POST请求。这就是我的解决方法:

postItem(itemData) {
    var observable = this.http.post('/api/items', itemData)
        .map(response => response.json()) // in case you care about returned json       
        .publishReplay(); // would be .publish().replay() in RxJS < v5 I guess
    observable.connect();
    return observable;
}

一旦调用connect(),请求就会被发送。但是,如果需要,postItem的调用者仍然可以订阅一个可观察对象。由于使用了publishReplay()而不是publish(),因此即使在POST请求完成后,仍然可以进行订阅。


这会抛出“error TS2339:类型'Object'上不存在属性'json'”。 - JacobIRR
2
如果其他人想在 RxJS 6 中使用此方法,您需要将 Observable 强制转换为连接它:const observable = this.http.post<T>('/api/items', itemData).pipe(publishReplay()); (observable as ConnectedObservable<T>).connect(); return observable; - kremerd
@kremerd ConnectableObservable 还未连接...谢谢! - Will Shaver

6

正如 @picci 所说,普通的 observables 都是 cold observables。如果您想发出请求,可以尝试使用 @lex82 的方法,这里是一个rxjs 6的草案:

import { ConnectableObservable } from "rxjs"
import { publish } from "rxjs/operators";

const myConnectableObservable: ConnectableObservable<any> = this._http.post('/list/items/update?itemId=' + itemId + "&done=" + done, null).pipe(publish()) as ConnectableObservable<any>;
myConnectableObservable.connect();

这基本上就像订阅但不进行真正的订阅。

https://blog.danlew.net/2018/09/25/connectable-observables-so-hot-right-now/


1
您可以像下面这样简单地使用toPromise方法:

public getEmployerListFromService() {
    const url = `/list/items/update?itemId=`;
    return this.http.get<any>(url).toPromise().then(response => {
      console.log(response);
    })
  }

并通过以下方式调用此方法:

 this.service.getEmployerListFromService();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接