2016-05-15 171 views
1

我可以使用一些幫助。我試圖在我的按鈕的鼠標中啓動我的ajax請求的實驗,但只有在用戶單擊時纔會消耗該請求的結果(或者當用戶單擊時請求還沒有完成,將結果作爲就這樣)。如果用戶離開按鈕而不點擊,則該請求應該被取消。Trxy蒸汽可觀察合併在rxjs

我卡在哪裏是如何合併點擊流和請求流。我無法使用withLatestFrom,因爲如果請求在點擊後完成,它將不會被使用。我也不能使用combineLatest,因爲如果在過去發生任何點擊,那麼請求將被消耗,即使我現在只是在閒逛。 會喜歡一些指導。這是一個有趣的問題來思考,但我堅持

const fetchContent = (url) => { 
    const timeDelay$ = Rx.Observable.timer(1000); // simulating a slow request 
    const request$ = Rx.Observable.create(observer => 
    fetch(url, { mode: 'no-cors' }) 
     .then(json => { 
     observer.onNext('res') 
     observer.onCompleted() 
     }) 
     .catch(e => observer.onError()) 
) 
    return timeDelay$.concat(request$) 
} 
const hover$ = Rx.Observable.fromEvent(myButton, 'mouseenter') 
const leave$ = Rx.Observable.fromEvent(myButton, 'mouseleave') 
const click$ = Rx.Observable.fromEvent(myButton, 'click') 

const hoverRequest$ = hover$ 
    .flatMap(e => 
    fetchContent(e.target.getAttribute('href')) 
     .takeUntil(leave$.takeUntil(click$)) 
) 

const displayData$ = click$ 
    .combineLatest(hoverRequest$) 

displayData$.subscribe(x => console.log(x)) 
+0

聽起來像'trial.js'庫所做的事情。參看https://github.com/MarkoCen/trial-js。不知道他們是否使用rxjs。 – user3743222

+0

感謝您的評論!我會看看它。作爲一個實驗,我更加努力地構建出來。 – user2689931

回答

2

您是不是非常遙遠實際。你只是錯過了包含zip真的。由於你真的需要傳播的是這兩個一個鼠標點擊的請求來完成。通過壓縮請求和鼠標點擊事件,你可以確保沒有其他發射。

const hover$ = Rx.Observable.fromEvent(myButton, 'mouseenter'); 
const leave$ = Rx.Observable.fromEvent(myButton, 'mouseleave'); 
const click$ = Rx.Observable.fromEvent(myButton, 'click'); 


//Make sure only the latest hover is emitting requests 
hover$.flatMapLatest(() => { 

    //The content request 
    const pending$ = fetchContent(); 

    //Only cancel on leave if no click has been made 
    const canceler$ = leave$.takeUntil(click$); 

    //Combine the request result and click event so they wait for each other 
    return Rx.Observable.zip(pending$, click$, (res, _) => res) 

       //Only need the first emission 
       .take(1) 

       //Cancel early if the user leaves the button 
       .takeUntil(canceler$); 

}); 
1

也許你可以概念化這三個事件(懸停,離開,點擊你給他們打電話)觸發三個動作(發出請求,取消請求,通請求結果)修改狀態(請求?傳遞請求?)。

現在,這是在上週日晚上倉促完成的,但幸運的一點點,這樣的事情可能工作:

function label(str) {return function(x){var obj = {}; obj[str] = x; return obj;}} 
function getLabel(obj) {return Object.keys(obj)[0];} 
const hover$ = Rx.Observable.fromEvent(myButton, 'mouseenter').map(label('hover')); 
const leave$ = Rx.Observable.fromEvent(myButton, 'mouseleave').map(label('leave')); 
const click$ = Rx.Observable.fromEvent(myButton, 'click').map(label('click')); 

var initialState = {request : undefined, response : undefined, passResponse : false}; 

var displayData$ = Rx.Observable.merge(hover$, leave$, click$) 
    .scan(function (state, intent){ 
      switch (getLabel(intent)) { 
      case 'hover' : 
       if (!state.request) { 
       state.request = someRequest; 
       state.response$ = Rx.Observable.fromPromise(executeRequest(someRequest)); 
       } 
      break; 
      case 'leave' : 
       if (state.request && !state.passResponse) cancelRequest(someRequest); 
       state.passResponse = false; 
      break; 
      case 'click' : 
       if (!state.request) { 
       state.response$ = Rx.Observable.fromPromise(executeRequest(someRequest)); 
       } 
       state.passResponse = true; 
      } 
     }, initial_state) 
    .filter(function (state){return state.passResponse;}) 
    .pluck('response$') 
    .concatAll()