有没有一种很好的方法来缩短Javascript承诺?

有没有一种很好的方法来缩短Javascript承诺?,javascript,promise,jquery-deferred,Javascript,Promise,Jquery Deferred,我是一个有点信誓旦旦的新手。有没有一个好的模式来处理这样的情况:一个人可能想要缩短一系列承诺的时间,不管是成功还是失败?在错误情况下,我知道您可以将.then(null,function(error){})链接到末尾,并从前面的任何then中捕获错误,但是如果您希望以更自定义的方式处理错误并终止,该怎么办?您会在早期的错误处理程序中指定错误的“类型”,并通过新的承诺返回它,以便在最终的错误处理程序中处理或跳过它吗?如果您希望在链中提前终止(仅有条件地触发任何后续的然后),那么成功案例又如何呢?通

我是一个有点信誓旦旦的新手。有没有一个好的模式来处理这样的情况:一个人可能想要缩短一系列承诺的时间,不管是成功还是失败?在错误情况下,我知道您可以将
.then(null,function(error){})
链接到末尾,并从前面的任何then中捕获错误,但是如果您希望以更自定义的方式处理错误并终止,该怎么办?您会在早期的错误处理程序中指定错误的“类型”,并通过新的承诺返回它,以便在最终的错误处理程序中处理或跳过它吗?如果您希望在链中提前终止(仅有条件地触发任何后续的
然后
),那么成功案例又如何呢?

通常,承诺链从调用某个异步函数开始,例如:

var promise = callAsync();
如果要链接第二个异步调用,可能会执行以下操作:

var promise = callAsync()
.then(function(){
    return callOtherAsync();
})
.then(function(){
    return callSuccessAsync();
}, function(){
    return callFailAsync();
});
作为链接的结果,
promise
现在包含最终承诺,当
callFinalAsync()
的承诺完成时,最终承诺完成。使用此模式时,没有办法缩短最终的
承诺
——您可以一路返回失败的承诺(例如,而不是返回callOtherAsync的结果),但这需要失败的承诺在整个链中进行(从而导致调用callFailAsync)。 您始终可以在回调中履行或拒绝
承诺

var promise = callAsync()
.then(function(){
    if(fail){
        promise.reject();
        //no way to halt progression 
    }else{
        return callOtherAsync();
    }
})
.then(function(){
    return callSuccessAsync();
}, function(){
    return callFailAsync();
});
但是,这不会阻止调用
callFailAsync()
。一些Promise/A实现为此目的公开了一个
stop
方法。使用stop,您可以执行以下操作:

var promise = callAsync();
.then(function(){
    if(fail){
        this.stop(); 
        promise.reject();
    }else{
        return callOtherAsync();
    }
})
.then(function(){
    return callSuccessAsync();
}, function(){
    return callFailAsync();
});
这取决于使用
this
访问中间承诺。一些Promise实现禁止这样做(强制将
this
设置为window/null/etc),但您可以通过闭包来处理这个问题


TL;DR:Promise/A spec不提供链短路功能,但添加一个并不困难。

不确定jQuery,但至少在任何Promise/A+中,您可以抛出:

.then(function() {
    if (skip) {
        throw new Error("skipping");
    }
})
//Chain of thens
.then(...)

.then(...)

.then(...)

.then(...)

.catch(function(){
    //skipped here
});

我假设您的用例如下所示:

promise
.then(a) 
.then(b); // We want to have an option to break here
.then(c)
.done(d)
处理这一问题的逻辑方法是:

promise
.then(a) 
.then(function (result) {
    if (something) throw new Error("Do not proceed!");
    return b(result).then(c).then(d);
}).done();

如果您不喜欢嵌套,可以将
b(result).然后(c).然后(d)
组合为外部函数。

我在应用程序中遇到了这个问题,通过使用一个简单的取消令牌对象实现了短路/取消,该对象可以在Promise的异常/拒绝处理程序回调中检查。也许不是最优雅的解决方案,但在不需要额外的库或替代/非标准的Promise实现的情况下,似乎工作得足够好

const cancellationToken = {};

somePromiseReturningMethod(...)
    .then(doSomething)
    .then(doSomethingElse)
    .catch(err => {
        if (err === cancellationToken)
        {
            // handle cancellation here and return
        }

        // handle "regular" errors here (show/log a message, etc)
    });

function doSomething(dataFromPromise)
{
    // check for whatever condition should result in cancellation/short-circuit
    if (...)
    {
        return Promise.reject(cancellationToken);
    }

    // carry on as normal...
}

method.success(函数(){}).error(函数(){})