如何从promise .then处理程序触发.fail处理程序

Tom*_*Tom 2 javascript jquery promise

tl; dr我可以在作为.then()链的一部分的函数中做什么来立即触发任何.fail()处理程序?(使用jQuery 1.9.1)

长版:

我有一堆测试和测试准备任务要执行,但有些是昂贵的,所以我希望按顺序执行它们.我写了这个:

$.when( gatherEasyData() )            // collect into for test #1
 .then( failIfDataBad )               // test #1

 .then( makeRestCall )                // fetch info for test #2
 .then( extractRestPayload )          // prepare info for test #2
 .then( failIfPayload1Unacceptable )  // test #2, based on REST info

 .then( makeHarderRestCall )          // fetch info for test #3
 .then( extractRestPayload )          // prepare info for test #3
 .then( failIfPayload2Unacceptable )  // test #3, based on expensive REST info

 .then( action1 )                     // success case!

 .fail( action2) ;                    // failure case :(
Run Code Online (Sandbox Code Playgroud)

我们的想法是,如果任何测试失败,或者任何测试准备工作失败,我想跳过更昂贵的任务并直接跳转到失败处理程序.

此外,依靠then将这些人联系在一起,实际的功能都不需要是承诺意识的; 他们可以专注于任何适合他们任务的合同,他们可以根据需要传递数据.例如:failIfDataBad(AKA测试#1)将接收由创建的配置的深度哈希gatherEasyData,并且该功能仅需要检查哈希return及其判定.因此,列表中的每个函数都返回数据或布尔值.

我发现我的失败案例都没有触发.fail.其余的呼叫使用制作$.ajax,而当那些回来与HTTP错误代码,action 2 调用的替代action 1.但是我的自定义测试似乎都不能使得到的步骤短路.

我的问题:我必须做什么才能failIfDataBad导致执行跳到.fail底部的处理程序?

请考虑这是当前的实现failIfDataBad:

function failIfDataBad(data) {
    if(!data) return false; // should trigger .fail
    if(data.prop1 === true) return false; // should trigger .fail

    if(data.prop2 > 500) return false; // should trigger .fail


    return true; // should permit next .then
}
Run Code Online (Sandbox Code Playgroud)

我试过(没有成功):

  • throw
  • return false
  • 没有回来

任何帮助表示赞赏.

use*_*654 7

你所要做的就是回复被拒绝的承诺.

如果他们正在执行任何异步操作,那么您的所有步骤都应该返回promises.

var success1 = function () {
    return $.Deferred(function (d){ return d.resolve();}).promise();
};
var success2 = function () {return $.Deferred(function (d){ return d.resolve();}).promise();};
var success3 = function () {return $.Deferred(function (d){ return d.resolve();}).promise();};
var fail = function () {
    return $.Deferred(function (d){ return d.reject();}).promise();
};
var success4 = function () {return $.Deferred(function (d){ return d.resolve();}).promise();};

success1()
    .then(success2)
    .then(success3)
    .then(fail)
    .then(success4)
    .done(function() {
        console.log("Successful. :(");
    })
    .fail(function () {
        console.log("Failure. :)"); // this one happens
    });
Run Code Online (Sandbox Code Playgroud)

success1-4只是返回已解决的承诺,同时fail返回被拒绝的承诺.

http://jsfiddle.net/43Mr8/

  • 这是jQuery promise api的许多问题之一.然而,由于它被如此广泛地使用,它不太可能很快被"修复".大多数承诺apis只是简单地使用throw并且最后有一个catch就足以打破链条,但jQuery承诺并非如此. (2认同)
  • 正确.如果您可以为不支持它的浏览器找到一个好的polyfil,那么本机Promise api可能更合适. (2认同)