web-dev-qa-db-ja.com

RxJは、結果のPromiseからObservableを作成します

私はRxJにかなり慣れていないので、RxをPromisesと組み合わせて使用​​するのが最善の方法を理解したいと思います。

私が作成したいのは、Angularのサービスで、イベントディスパッチャーパターンとして機能し、promiseが完了するとイベントを発行します。また、必要なのは、(event )オブザーバブルのサブスクライバーが呼び出されることはありません。最後に、オブザーバブルの後続のサブスクライバーは、サーバーへの別の要求をトリガーせずに同じ結果を取得します。ここで独自のソリューションを実装できました。

// ... CountryService code

var COUNTRIES_LOADED = Rx.Observable
    .create(function (observer) {
        $http
            .get('/countries')
            .then(function (res) {
                observer.onNext(res);
            }, function (err) {
                observer.onError(err);
            })
            .finally(function () {
                observer.onCompleted();
            });
    })
    .shareReplay();

これで、新しい「リスナー」をサブスクライブして、オブザーバブルをサブスクライブするたびにプルされます。新しいサブスクライバーは、サーバーに再度アクセスしなくても値がキャッシュされます。

したがって、私の「消費者」(Angular Directive)内で、次のようなことをしたいと思います。

// ... countryInput directive code:

COUNTRIES_LOADED.subscribe(function (response) {
    // Fill in countries into scope or ctrl
    scope.countries = response.countries;
});

COUNTRIES_LOADEDオブザーバーの将来のサブスクライバーは、$ httpリクエストをトリガーしてはなりません(MUSTNOT)。同様に、ディレクティブがページに含まれない場合、$ httpが呼び出されることはありません。

上記の解決策は機能しますが、このアプローチの潜在的な欠点とメモリへの影響を認識していません。これは有効な解決策ですか? RxJを使用してこれを達成するためのより良い/より適切な方法はありますか?

どうもありがとう!

13
Max101

私はここで答えを見つけました(少し違う名前が付けられています) rxjsはサブスクライブ時にpromiseを1回だけ使用します

したがって、私の例では、答えは次のように単純です。

var loadCountries = function () { return $http.get('/countries'); };

var observable = Rx.Observable.defer(loadCountries).shareReplay();
4
Max101

Rx.Observable.fromPromise(promise)を使用する

fromPromise:

Promises/A +仕様に準拠したPromiseおよび/またはES2015に準拠したPromise、またはそのPromiseを監視可能なシーケンスに戻すファクトリ関数を変換します。

例:

var source = Rx.Observable.fromPromise(promise);

var subscription = source.subscribe(
  function (x) {
    console.log('Next: %s', x);
  },
  function (err) {
    console.log('Error: %s', err);
  },
  function () {
    console.log('Completed');
  });

更新

rxjs6メソッドは from

7
cmd

更新

rxjs6の時点で、 from() を使用できます。


rxjs5fromPromise() AP​​Iを使用しようとしましたか?

ドキュメントを確認してください ここ

3
Clement

これがObservablesの使用方法です。getuser(username)というメソッドがあるとします。

//Returns an observable
getUser(username){
    return $http.get(url)
        .map(res => res.json());
}

そして、あなたはそれを以下のように使うことができます

getUser.subscribe(res => console.log(response));

しかし、promiseを使用したい場合

//Returns an Promise
//Donot forget to import toPromise operator
getUser(username){
    return $http.get(url)
        .map(res => res.json())
        .toPromise();
}

そして、あなたはそれを以下のように使うことができます

getUser.then(res => console.log(response));
1