创建一次性订阅


180

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

是否有类似的东西:

observable.subscribeOnce(func);

我的用例是,我在快速路由处理程序中创建一个预订,每个请求被多次调用。

Answers:


318

无法100%确定所需的内容,但是如果您只想观察第一个值,请使用first()take(1)

observable.first().subscribe(func);

注意:满足条件时.take(1).first()两者都会自动退订

从RxJS 5.5+更新

摘自Coderer的评论。

import { first } from 'rxjs/operators'

observable
  .pipe(first())
  .subscribe(func);

这就是为什么


31
订阅后会自动清理吗?
伯克利·马丁内斯

49
是的,它确实。满足条件时,先采取并先取消订阅。
布兰登2015年

20
为什么文档没有说它自动处理了订阅?
jzig

17
RxJS的一般规则是,可观察流结束时将处理订阅。这意味着任何“缩短”流(或将其转换为不同类型的流)的运算符将在其操作完成后从源流退订。我不确定文档中的位置或位置。
布兰登

36
如果有人在2018年来到这里,您实际上想要的observable.pipe(first()).subscribe(func)是哪里first来的rxjs/operators
Coderer

32

RxJS拥有我见过的一些最好的文档。单击波纹管链接将带您到一个非常有用的表,其中将用例映射到运算符。例如,在“我要采取的第一个值”的使用情况:三家运营商:firstfirstOrDefaultsample

注意,如果可观察的序列没有通知完成,那么first操作员会向错误通知订户,而操作员会向订户firstOrDefault提供默认值。

操作员用例查找


3

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


非常有趣的,这也意味着我们只要awaitpromise这使得一个衬垫
路易·阿尔梅达

@LouieAlmeda您能给我们一个班轮的例子吗?
Ado Ren

@AdoRen,您好,我在这里为您解释了该技术,希望对您有所帮助。
路易·阿尔梅达

2

为了补充@Brandon的答案,使用first()或类似方法对于基于的更新a也是必不可少BehaviorSubjectObservable。例如(未测试):

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);
  });

2

干净方便的版本

扩展了M FuatNUROĞLU关于将可观察者转换为承诺的惊人答案,这是它的非常方便的版本。

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如果您不希望包含函数异步,也可以只是承诺

我不确定这种方法是否存在折衷,请随时在评论中让我知道,以便我们知道。

PS:如果您喜欢这个答案,别忘了同时赞扬M FuatNUROĞLU的答案:)


0

我有类似的问题。

下面甚至从不同的状态转换器调用。如我所愿。

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)

希望对您有帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.