在NodeJS中实现阻塞控制流程

时间:2016-06-09 17:36:35

标签: javascript node.js promise

我正在尝试创建一个阻塞控制流程,但已经走到了尽头。 这个想法是请求进入并流经许多处理函数。每个功能都会执行某些操作,并决定是否现在满足请求。如果是,则处理停止,否则,调用下一个处理程序。 每个处理程序可能会也可能不会异步执行某些操作(如获取/写入数据)。如果是这种情况,那么以下处理程序取决于启动之前的数据。

到目前为止,我有两个想法,它们都不符合这些要求: 1)所有处理程序都是函数,它们被推入一个数组并用some迭代。如果处理程序希望停止控制流,则只需返回true。 使用这种方法,我不能让任何处理程序调用异步函数。

2)所有处理程序都是链接的承诺。这对我来说似乎是一个更好的主意,但我无法弄清楚如何最好地处理停止控制流程。我有两个想法: - 一旦处理程序决定中断流,保留一个设置为true的变量。在每个处理程序中检查此值,并在需要时立即解决。这意味着很多重复的代码。 - 拒绝承诺,如果它不希望继续正常流程,并继续catch。但是,使用错误作为控制流程的一种手段的想法让我很痛苦 - 这也意味着我必须处理由于实际错误而调用catch的情况。

我的蜘蛛般的感觉告诉我必须有另一种方式,但我无法弄明白。

2 个答案:

答案 0 :(得分:5)

您可以根据需要使用ES6生成器生成承诺。每当一个promise解析它就可以检查一个停止值,如果为false(即继续执行下一个处理程序),则从迭代器中请求下一个。

function* promiseHandlers() {
  const handlers = [
    promiseHandler1,
    promiseHandler2,
    promiseHandler3,
    promiseHandler4,
    promiseHandler5
  ];

  for (const handler of handlers) {
    yield handler();
  }
}

function run(iter) {
  const i = iter.next();
  if (i.done) {
    return Promise.reject(new Error("end of iterator reached"));
  }
  return Promise.resolve(i.value).then(result => result || run(iter));
}

run(promiseHandlers());

这实际上不是链接。相反,它将按顺序执行每个promiseHandler,但这些的结果不会传递给下一个。我认为这对OP想要的是正确的,因为一个真实的结果会结束迭代(即休息)。

答案 1 :(得分:3)

不要将承诺处理程序链接起来,嵌套它们。您可以通过一系列函数以编程方式执行此操作:

var handlers = […]; // functions that can return promises

var run = handlers.reduceRight(function(next, handler) {
    return function() {
        return Promise.resolve(someArg).then(handler).then(function(result) {
            if (result) // true, whatever
                return result;
            else
                return next();
        });
    };
}, function end() {
    return Promise.reject(new Error("no handler matched"));
});

run().then(function(result) {
    // the result from the first handler that returned anything
}, function(err) {
    // some handler threw an exception, or there was no handler
});