创建一次性订阅

Create one-time subscription

我需要创建对 Observable 的订阅,该订阅会在首次调用时立即处理掉。

是否有类似的东西:

observable.subscribeOnce(func);

我的用例,我在快速路由处理程序中创建订阅,每个请求都会多次调用订阅。

不能 100% 确定您需要什么,但如果您只想观察第一个值,则使用 first()take(1):

observable.first().subscribe(func);

注意:.take(1).first() 都会在满足条件时自动取消订阅

从 RxJS 5.5+ 更新

来自 的评论。

import { first } from 'rxjs/operators'
    
observable
  .pipe(first())
  .subscribe(func);

Here's why

RxJS 有一些我见过的最好的文档。按照下面的 link 将带您到一个非常有用的 table 将用例映射到操作符。例如,在 "I want to take the first value" 用例下有三个运算符:firstfirstOrDefaultsample.

请注意,如果可观察序列在没有通知的情况下完成,则 first 运算符会通知订阅者错误,而 firstOrDefault 运算符会向订阅者提供默认值。

operator use case lookup

为了补充 ,使用 first() 或类似的方法对于基于其 Observable 更新 BehaviorSubject 也是必不可少的。例如(未经测试):

var subject = new BehaviorSubject({1:'apple',2:'banana'});
var observable = subject.asObservable();

observable
  .pipe(
    first(), // <-- Ensures no stack overflow
    flatMap(function(obj) {
      obj[3] = 'pear';
      return of(obj);
    })
  )
  .subscribe(function(obj) {
    subject.next(obj);
  });

更新(DEC/2021):

由于 toPromise() 函数已在 RxJS 7 中弃用,因此已宣布使用新函数代替它。 firstValueFromlastValueFrom.

firsValueFrom 函数解析第一个发出的值并直接取消订阅资源。当 Observable 完成但没有发出任何值时,它用 EmptyError 拒绝。

另一方面,lastValueFrom 函数在某种程度上与 toPromise() 相同,因为它解析可观察对象完成时发出的最后一个值。但是,如果 observable 不发出任何值,它将以 EmptyError 拒绝。与 toPromise() 不同,后者在没有值发出时解析 undefined

更多信息,请查看docs


旧答案:

如果你只想调用一个 Observable 一次,这意味着你不会等待来自它的流。因此,在您的情况下使用 toPromise() 而不是 subscribe() 就足够了,因为 toPromise() 不需要取消订阅。

简洁方便的版本

扩展 M Fuat NUROĞLU 关于将 observable 转换为 promise 的惊人答案,这是它的非常方便的版本。

const value = await observable.toPromise();

console.log(value)

这样做的美妙之处在于我们可以像普通变量一样使用该值而无需引入另一个嵌套块!

当您需要从多个可观察对象中获取多个值时,这尤其方便。干净整洁。

const content = await contentObservable.toPromise();
const isAuthenticated = await isAuthenticatedObservable.toPromise();

if(isAuthenticated){
   service.foo(content)
}

当然,如果你要走这条路,你将不得不创建你的包含函数async。如果您不希望包含的函数是异步的,您也可以 .then 承诺

我不确定这种方法是否有优缺点,请随时在评论中告诉我,以便我们了解。

P.S。如果你喜欢这个答案,别忘了给 M Fuat NUROĞLU 的答案点赞:)

我也有类似的问题。

Below 稍后被不同的状态转换器调用。因为我不想。

function foo() {
    // this was called many times which was not needed
    observable.subscribe(func);
    changeObservableState("new value");
}

我决定尝试 unsubscribe() 订阅如下。

function foo() {
    // this was called ONE TIME
    observable.subscribe(func).unsubscribe();
    changeObservableState("new value");
}

subscribe(func).unsubscribe(); 就像 subscribeOnce(func).

希望对你也有帮助。

observable.pipe(take(1)).subscribe() 使用 take 1 订阅一次然后退出