2017-07-25 23 views
0

在下面的代碼,我有一個很難理解的鏈式調用的順序是: 調用的可觀察代碼的順序是什麼?

function registerDomain(caseWebsiteUrl) { 
    return this._adminService.registerDomain(caseWebsiteUrl.Url) 
     .concatMap(registerId => Observable.interval(5000) 
     .mergeMap(() => this._adminService.getChange(registerId)) 
     .takeWhile((info) => info.ChangeInfo.Status.Value !== 'INSYNC') 
    ) 
    } 
    registerDomain.subscribe(res => console.log('res:'+res)); 

我試圖理解上面的代碼,但我有很難理解的順序。這是我更容易理解,當我看到一個更簡單的例子是這樣的:

function registerDomain() { 
    return register() 
     .concatMap(registerId => Rx.Observable.interval(5000) 
     .mergeMap(() => 
      getChange(registerId)) 
     .takeWhile((info) => info === 'PENDING') 
    ); 
    } 

    registerDomain().subscribe(x=>console.log(x)); 



    function register() 
    { 
    return Rx.Observable.of("registerId"); 
    } 


    function getChange(registerId) 
    { 
    //at some point this will return INSYNC 
    return Rx.Observable.of("PENDING"); 
    } 

當我看到這個代碼,我看它的方式是:

  1. 通話記錄()返回可觀察
  2. 將getChange()和takeWhile合併爲一個可觀察對象
  3. 將getChange和TakeWhile的合併結果與間隔Observable連接起來。
  4. 呼叫getChange每5秒鐘,直到狀態!== '待定'

是我的上述評估是否正確?你怎麼知道什麼時候使用合併或concat?

如果我想捕獲錯誤,例如,register()拋出一個錯誤,那麼它應該失敗。

基於@馬克麪包車Straten的回答,一些額外的問題:

  1. 所以,如果我想維持秩序,我應該使用concatMap?在這種情況下,我希望registerDomain在調用getChange之前完成?

  2. 如果我不關心順序,那麼使用mergeMap?

  3. 在getRegisterStatus方法中,它究竟在哪裏合併?爲什麼不使用concatMap?

+0

concatMap確實是保序。該代碼假定您希望在開始輪詢註冊表中的更改之前完成「registerDomain()」。如果不是這種情況,可以將它合併到一起,但'getChange'依賴於'registerDomain()'返回的'registerId'。 getChange的mergeMap()是因爲'adminService.getChange()'很可能會返回'Observable '或'Promise ',您需要將其平鋪到主流中。 –

回答

1

有三家運營商壓扁高階觀測:

  • mergeMap(又名flatMap) - 合併所有流在一起,排放交錯
  • concatMap - 第一個流完成CONCAT後下一個等
  • switchMap - 放棄第一個流,開關下一個流到達時 因此給予代碼:
function registerDomain(caseWebsiteUrl) { 
    return this._adminService.registerDomain(caseWebsiteUrl.Url) 
     .concatMap(registerId => Observable.interval(5000) 
     .mergeMap(() => this._adminService.getChange(registerId)) 
     .takeWhile((info) => info.ChangeInfo.Status.Value !== 'INSYNC') 
    ) 
    } 
    registerDomain.subscribe(res => console.log('res:'+res)); 

我們可以改寫這個如下:

function registerDomain(caseWebsiteUrl) { 
    return this._adminService.registerDomain(caseWebsiteUrl.Url) 
    .concatMap(registerId => getRegisterStatus(registerId)) 
} 

function getRegisterStatus(registerId) { 
    return Observable.interval(5000) 
    .mergeMap(() => this._adminService.getChange(registerId)) 
    .takeWhile((info) => info.ChangeInfo.Status.Value !== 'INSYNC') 
} 
  1. 首先_adminService .registerDomain返回一個可觀察

  2. 當它發出一個值後,我們concatMap seco nd可觀察從getRegisterStatus返回

  3. getRegisterStatus當檢索到的信息變爲'INSYNC'時,完成每個非INSYNC發射。

我不認爲是真正需要的concatMap,可與mergeMap被替換,因爲registerDomain很可能只發出一個值

+0

嗨,感謝迄今爲止的答案,我在我的文章中提出了一些其他問題。現在我獲得了更好的concatMap,但仍然很難理解mergeMap,特別是對於這種情況? – xaisoft

相關問題