如何在RXJS中链接承诺列表?

时间:2017-08-30 08:55:30

标签: javascript asynchronous rxjs rxjs5

如何在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);

但这基本上可以立即执行所有承诺。

2 个答案:

答案 0 :(得分:1)

您的尝试似乎非常接近。

您可以为.flatMap指定最大并发度1,例如:

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

或等效使用.concatMap代替.flatMap

Observable.fromArray(workTodo)
 .concatMap(doTodoAsync)

我会使用concatMap,因为它感觉更加惯用。

更新: DEMO

答案 1 :(得分:0)

一些递归怎么样?

首先创建一个递归函数并将其命名为recursiveDoToDo

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

上面的代码只是将您的doTodoAsync包装到一个Observable中,然后我们映射结果以返回已解析的promise 数组的index,以便递归使用后面。

接下来,我们将使用.expand()运算符递归调用recursiveDoToDo

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

你需要为递归做的只是将索引递增1.因为.expand()将递归地递归运行,.take()运算符会告诉observable何时结束流,这是worktodo的长度。

现在您可以直接订阅它:

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

以下是working JS Bin