2016-11-17 27 views

回答

5

這個問題是對RxJS如何工作的微妙但嚴重的誤解 - 但不要害怕,這是很常見的。

所以給你的例子:

const pingEpic = action$ => 
    action$.ofType(PING) 
    .delay(1000) 
    .mapTo({ type: PONG }) 
    .takeUntil(action$.ofType(CANCEL)); 

這部史詩的行爲可以被描述爲過濾不匹配類型PING所有操作。當一個動作匹配時,等待1000ms,然後將該動作映射到不同的動作{ type: PONG },該動作將被髮射,然後由可觀察到的可見度分派。如果在任何時間,而應用程序正在運行某人發送類型CANCEL類型的動作,然後取消訂閱從源代碼,這意味着整個鏈將取消訂閱,終止史詩。

這可能是有益的,看看怎麼這個樣子,如果你這樣做是勢在必行:

const pingEpic = action$ => { 
    return new Rx.Observable(observer => { 
    console.log('[pingEpic] subscribe'); 
    let timer; 

    const subscription = action$.subscribe(action => { 
     console.log('[pingEpic] received action: ' + action.type); 

     // When anyone dispatches CANCEL, we stop listening entirely! 
     if (action.type === CANCEL) { 
     observer.complete(); 
     return; 
     } 

     if (action.type === PING) { 
     timer = setTimeout(() => { 
      const output = { type: PONG }; 
      observer.next(output); 
     }, 1000); 
     } 
    }); 

    return { 
     unsubscribe() { 
     console.log('[pingEpic] unsubscribe'); 
     clearTimeout(timer); 
     subscription.unsubscribe(); 
     } 
    }; 
    }); 
}; 

你可以運行該代碼,用假店在這裏:http://jsbin.com/zeqasih/edit?js,console


相反,你平時想要做的是隔離你想從可以無限期收聽的頂級鏈路中取消的用戶鏈。雖然您的示例(從文檔修改)是人爲設計的,但我們先來看看它。

這裏我們使用mergeMap算子讓我們採取匹配的動作並映射到另一個獨立的可觀察鏈

演示:http://jsbin.com/nofato/edit?js,output

const pingEpic = action$ => 
    action$.ofType(PING) 
    .mergeMap(() => 
     Observable.timer(1000) 
     .takeUntil(action$.ofType(CANCEL)) 
     .mapTo({ type: PONG }) 
    ); 

我們使用Observable.timer等待1000毫秒,然後映射它發出的值(這恰好是是數字零,但是這不是在這裏重要的),我們PONG行動。我們還說我們想從定時器源「取」,直到它正常完成或者我們收到類型爲CANCEL的動作。

這會隔離鏈,因爲mergeMap將繼續訂閱您返回的可觀察值,直到它出錯或完成。但是,當發生這種情況時,它不會本身停止訂閱您將其應用到的源;本例中的action$.ofType(PING)

一個更現實的例子是在Cancellation section

在這裏,我們放在.takeUntil()我們.mergeMap()內,但經過我們的AJAX調用後的終極版,可觀察到的文檔;這很重要,因爲我們只想取消AJAX請求,而不是阻止Epic聽取任何未來的操作。

const fetchUserEpic = action$ => 
    action$.ofType(FETCH_USER) 
    .mergeMap(action => 
     ajax.getJSON(`/api/users/${action.payload}`) 
     .map(fetchUserFulfilled) 
     .takeUntil(action$.ofType(FETCH_USER_CANCELLED)) 
    ); 

這一切聽起來可能令人困惑,但像最強大的東西,一旦你得到它,它會變得直觀。 Ben Lesh在解釋Observables如何在his recent talk中工作方面做得非常出色,包括討論運營商如何成爲觀察者鏈,甚至討論隔離用戶鏈。儘管談話是在AngularConnect上進行的,但它並不是Angular特有的。


另外,重要的是要注意,你的史詩不會吞下或以其他方式防止動作到達減速器,例如,當您將傳入的動作映射到另一個動作時。事實上,當你的史詩收到一個動作,它已經通過你的減速器已經通過。把你的史詩看作邊車流程,它監聽你的應用程序動作流,但不能阻止正常的重複事件發生,它只能發出新的動作。

+0

謝謝你的詳細解答。 –

+0

@АртёмХитрик不客氣! – jayphelps