我怎样才能绕过承诺链中的剩余部分,就像传统的回归'声明?

时间:2016-04-05 18:21:41

标签: javascript promise es6-promise

我将离开我的同步,多线程Java编程世界,并拥抱ES6 JavaScript的单线程,异步,基于承诺的世界。我不得不接受这种将同步样式编写的函数映射到基于异步承诺的函数的概念。我目前正在使用ES6原生Promise和蓝鸟承诺的混合。

我将从一个示例开始为我的问题设置阶段(Java中的同步示例,ES6中的异步示例):

同步功能

private Object doSomething(Object var1, Object var2) {
    Object var3 = blockingFunction(var1);
    Object var4 = anotherBlockingFunction(var2, var3);
    return var4;
}

基于异步承诺的equivlanet

function doSomething(var1, var2) {
    return asyncFunction(var1)
    .then(var3 => {
        return anotherAsyncFunction(var2, var3);
    })
    .then(var4 => {
        return var4;
    });
}

现在我的问题:是否有一种干净的(即内置的,已经想到的)方式来模拟同步return想法绕过其余的回归链?

为了解释,这里有两个同步和异步的例子:

同步功能

private Object doSomething(Object var1, Object var2) {
    Object var3 = blockingFunction(var1);
    Object var4 = anotherBlockingFunction(var2, var3);
    if (!var4.isValid()) {
        return var3;
    }
    // If var4.isValid() equates to false, we bypass the following statements
    // and return the value of var3 as the final value
    Object var5 = var4.validateObject();
    var5.setSomething(var1);
    return var5;
}

(我的猜测是)基于异步承诺的等效

function doSomething(var1, var2) {
    // Predefine variables within this block so they persist between 'then's
    let var3;
    let var4;
    let var5;
    let bypassCondition;
    return asyncFunction(var1)
    .then(result => {
        var3 = result;
        return anotherAsyncFunction(var2, var3);
    })
    .then(result => {
        var4 = result;
        bypassCondition = !var4.valid;
        if(bypassCondition) {
            return var3;
        }
    })
    .endChain(bypassCondition)
    // If the bypassCondition is true, the entire chain would return the value
    // of the previous then's return;
    // Otherwise, if false, the chain continues
    .then(() => {
        return var4.validateObject();
    })
    .then(result => {
        var5 = result;
        var5.something = var1;
        return var5;
    });
}

这样的事情是否已经存在?

我知道这些替代方案,所以也许我可以告诉它们是否真的是正确的方法:

  • 在链中间抛出异常并在结尾捕获它,以便绕过其他语句
  • then块中的每个后续if (!bypassCondition)函数换行,以便它们不会被执行

2 个答案:

答案 0 :(得分:1)

你所说的是承诺链中的条件流,早期的回报是有用的。

是的,通过有条件地分支您的连锁店是可能的。请密切注意括号:

function doSomething(var1, var2) {
  return asyncFunction(var1)
  .then(var3 => anotherAsyncFunction(var2, var3))
  .then(var4 => (!var4.isValid())? var3 : var4.validateObject()
    .then(var5 => (var5.something = var1, var5)));
}

请注意最后一行的缩进,.then不在var4.validateObject()

这很好地映射到ES7(我们可以提前保释):

async function doSomething(var1, var2) {
  let var3 = await asyncFunction(var1);
  let var4 = await anotherAsyncFunction(var2, var3);
  if (!var4.isValid()) {
    return var3;
  }
  let var5 = await var4.validateObject();
  var5.something = var1;
  return var5;
}

(你没有说明validateObject是否异步,所以我选择了异步)。

答案 1 :(得分:1)

This answer over here是我能够获得这个问题的答案的地方。

正如Bergi指出的那样,我在这里所做的就是分支。我需要做的就是将继续分支放在 else块中,如下所示:

function doSomething(var1, var2) {
    // Predefine variables within this block so they persist between 'then's
    let var3;
    let var4;
    let var5;
    return asyncFunction(var1)
    .then(result => {
        var3 = result;
        return anotherAsyncFunction(var2, var3);
    })
    .then(result => {
        var4 = result;
        if(!var4.valid) {
            return var3;
        }
        else {
            return Promise.resolve()
            .then(() => {
                return var4.validateObject();
             })
             .then(result => {
                var5 = result;
                var5.something = var1;
                return var5;
             });
        })
    }
}

从根本上说,无法停止承诺链。即使它看起来我应该能够,但请记住,其他函数会将.then(...)附加到函数的输出中。代码没有区分then语句是出现在一个函数内还是出现在函数外部,因此我提议的.endchain(...)必须结束承诺链的所有其他用户在函数外部,使链最终无法使用。

使用这种分支方法,我完成的传统return行为已经完成,因为函数结束前链中的最后一个then是链返回值时的链接在函数之外使用 - 在这种情况下,return var3;如果var4.validfalse,或者return var5;之后。