web-dev-qa-db-ja.com

関数からObservableを作成する方法は?

関数を(同期的に)呼び出して、その戻り値を初期エミッションとして使用します(結果のオブザーバブルで他のいくつかの演算子をチェーンします)。

サブスクリプション中にこの関数を呼び出したいので、Observable.of(() => getSomeValue())を使用できません。私はbindCallback(以前はfromCallback)を見てきましたが、このタスクに使用できるとは思いません(私が間違っている場合は修正してください)。私はv4のドキュメントでstart静的演算子を見てきましたが、どうやらそれはv5には実装されていません(その途中の兆候はありません)。 RxJavaにはfromCallable演算子もあり、これはまさにその面倒です。

私が考えることができる唯一の方法は次のとおりです:

_Observable.create((observer: Observer<void>) => {
  let val = getSomeValue();
  observer.next(val);
  observer.complete();
})
_

それだけだと思います。しかし、これはおそらくObservable.fromFunction(() => getSomeValue())のような単純なものでは非常に複雑に思われ、start演算子のように非同期に実行したい場合はどうなりますか? RxJSの現在のバージョンでこれを行うにはどうすればよいですか?

17
Titan

Observable.createを明示的に使用することはできる限り避けますが、これは一般に、イベントの発行だけでなく分解ロジックも管理する必要があるため、バグの原因となるためです。

代わりに Observable.defer を使用できます。 ObservableまたはObservable-likeを返す関数を受け入れます(読み取り:Promise、Array、Iterators)。したがって、非同期のものを返す関数がある場合は、次のように簡単です。

Observable.defer(() => doSomethingAsync());

これを同期結果で動作させたい場合は、次のようにします。

Observable.defer(() => Observable.of(doSomethingSync()));

注:createと同様に、サブスクリプションごとに関数が再実行されます。これは、関数を再実行せずに関数呼び出しの結果を格納するObservable.bindCallbackの結果とは異なります。したがって、そのような動作が必要な場合は、適切なmulticasting演算子を使用する必要があります。

20
paulpdaniels

プロジェクトで使用したfromFunction$の実装:

function fromFunction$<T>(factory: () => T): Observable<T> {
    return Observable.create((observer: Subscriber<T>) => {
        try {
            observer.next(factory());
            observer.complete();
        } catch (error) {
            observer.error(error);
        }
    });
}

次のように使用:

fromFunction$(() => 0).subscribe((value) => console.log(`Value is '${value}'`), null, () => console.log('Completed'));
fromFunction$(() => [1, 2, 3]).subscribe((value) => console.log(`Value is '${value}'`), null, () => console.log('Completed'));
fromFunction$(() => { throw 'Something' }).subscribe(null, (error) => console.error(`Error: ${error}`));

与える:

Value is '0'
Completed

Value is '1,2,3'
Completed

Error: Something

そのような実装が存在するまで。

4
Matt

実際、私は最良のオプションは_Observable.create_を使用することだと思います。

同期関数を使用すると確信している場合は、 startWith() 演算子を使用できます(これは、getSomeValue()からの戻り値が同じである場合にのみ有効になりますすべてのオブザーバー向け)。

ソースとして_Observable.bindCallback_を使用することはもちろん可能ですが、コードを理解するのが非常に難しくなり、_Observable.create_だけを使用できるため、通常は必要ないため、個人的には避けることをお勧めします。

2
martin