2016-08-05 45 views
6

对RxJs来说我相当新,我想了解什么是最好的方法是将Rx与Promises结合使用。RxJs从生成的Promise创建Observable

我想创建的是Angular中的服务,它的作用与事件调度程序模式非常相似,并在完成承诺后发出事件。我还需要的是,如果没有(事件)订户,那么observable永远不会被调用。我想要发生的最后一件事是任何后续的observable订阅者都会得到相同的结果,而不会触发另一个请求到服务器。 我已成功地实现在这里我自己的解决方案:

// ... 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(); 

现在,只要我订阅了新的“听众”,以主题的观察到的将被拉动。任何新的订户都将获得缓存的值,而不会再次触摸服务器。

所以在我的“消费者”(角指令)我愿做这样的事情:

// ... countryInput directive code: 

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

到COUNTRIES_LOADED观察者的任何未来的用户也不得触发$ HTTP请求。同样,如果该指令从未包含在页面中,$ http将永远不会被调用。

上述解决方案的工作,但我不知道这种方法的潜在缺陷和内存影响。这是一个有效的解决方案?使用RxJs有更好/更合适的方法来实现这一点吗?

非常感谢!

+1

检查此链接使用rxjs与angularjs http://cvuorinen.net/2016/05/using-rxjs-observables-with-angularjs-1/ –

+0

您的解决方案看起来不错,我不认为你能想出比这更好的东西。 – estus

回答

1

您是否尝试过使用fromPromise() API rxjs5

检查它的文档here

+0

是的,我知道fromPromise,但只有当已经有承诺存在时才会发生。我要求的是,如果没有订阅者,$ http调用永远不会被执行。 – Max101

1

这就是你可以如何使用Observables 可以说你有一个方法getuser(username)

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

而且你可以使用它作为下面

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

,但如果你想使用的承诺

//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)); 
+0

好吧,对不起,也许问题不是很清楚。我确实知道如何使用和使用observables,我想知道的是如何在一个只有被调用的observable中“包装”一个HTTP调用,如果有/有任何订户。 – Max101

+0

这个答案的主要问题是'$ http.get' *不*返回一个Observable。它返回一个Promise。这是Angular的'Http'和AngularJS的'$ http'之间的巨大差异。 – daemonaka

4

我在这里找到了答案(只是略有不同ntly命名) rxjs using promise only once on subscribe

所以对于我的例子中,答案是简单的:

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

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

使用Rx.Observable.fromPromise(promise)

fromPromise:

一个承诺/ A +规格的转换兼容Promise和/或ES2015兼容 承诺或工厂功能,将所述承诺返回到 可观察序列。

例如:

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