2016-08-05 46 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'); 
    });