2017-08-30 51 views
1

如何鏈接RXJS中的承諾列表?每一個承諾需要執行時,先前解決(工作todo是有狀態的)。如何鏈接RXJS中的承諾列表?

我現在做它的方式原始的感覺:

const workTodo = []; // an array of work 
const allWork = Observable.create(observer => { 
    const next=() => { 
    const currentTodo = workTodo.shift(); 
    if (currentTodo) { 
     doTodoAsync(currentTodo) 
     .then(result => observer.onNext(result)) 
     .then(next); 
    } else { 
     observer.onCompleted(); 
    } 
    }; 
    next(); 
}); 

我的想法是這樣的:

const workTodo = []; // an array of work 
const allWork = Observable 
        .fromArray(workTodo) 
        .flatMap(doTodoAsync); 

但在一次基本上執行所有的承諾。

回答

0

有些遞歸怎麼樣?

首先創建一個遞歸函數,並調用它recursiveDoToDo

const recursiveDoToDo = (currentTodo, index) => 
    Observable 
     .fromPromise(doTodoAsync(currentTodo)) 
     .map(resolved => ({resolved, index})); 

上面簡單的代碼封裝您doTodoAsync到可觀察到的,然後我們的結果映射到返回的解決承諾的的index數組,用於遞歸使用。

接下來,我們將使用.expand()運算符遞歸調用recursiveDoToDo

recursiveDoToDo(worktodo[0], 0) 
    .expand(res => recursiveDoToDo(worktodo[res.index + 1], res.index + 1)) 
    .take(worktodo.length) 

所有你需要爲你的遞歸做的只是通過1遞增索引,因爲.expand()將遞歸一直運行下去,在.take()運營商有沒有告知觀察到何時結束流,這是長你的worktodo

現在,你可以簡單地訂閱它:

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

這裏是working JS Bin

+0

看來工作,但它似乎也簡陋。我想我更喜歡遞歸電話。我覺得應該有一個簡單的操作員來做到這一點。 – nicojs

1

看來你是非常接近你的嘗試。

您既可以指定1最大併發數爲.flatMap,如:

Observable.fromArray(workTodo) 
.flatMap(doTodoAsync, 1) 

或等效採用.concatMap代替.flatMap

Observable.fromArray(workTodo) 
.concatMap(doTodoAsync) 

我會用concatMap,因爲它感覺更地道。

UPDATE:DEMO

+0

我測試過'concatMap',但它看起來有點不同。它並行執行'doTodoAsync',然後按照原始順序組合結果。這裏還描述:http://reactivex.io/documentation/operators/flatmap.html。 flatMap上的第二個參數作爲'number'似乎不存在。 – nicojs

+0

@nicojs不知道你到底是什麼意思。用正在運行的演示更新答案。它清楚地表明,任務是一個接一個執行的,並且'mergeMap/flatMap'接受'concurrency'參數,如下所述:http://reactivex.io/rxjs/class/es6/Observable。JS〜Observable.html#實例方法,mergeMap。 –