javascript - 如何使用 deferred() 顺序触发 JQuery 函数?

标签 javascript jquery

我真的很难理解 jquery 中的 deferred() 方法。我花了几个小时阅读文档,但我仍然不完全理解我在做什么。

我的基本问题是,我有一系列函数(不是 ajax 调用),我想按顺序运行它们,但如果其中任何一个出现错误,则停止所有进程。

这是我已经取得的进展(我删除了一堆不需要的代码,只留下基本想法)

//The module  var myModule = (function() {

//Defaults
var vOne;
var VTwo;
var deferred = $.Deferred();

//Private method
var _myPrivateFunction1 = function(userID) {
    if(userID >= 10) {
        //All is good, set var vOne to true and run next function
        vOne = true;
        return deferred.promise();
    } else {
        //User is not allowed, stop everything else and show the error message
        return deferred.reject();
    }
}

var _myPrivateFunction2 = function() {
    if(vOne === true) {
        //Ok we can keep going
        return deferred.promise();
    } else {
        //again stop everything and throw error
        return deferred.reject();
    }
};

var _myPrivateFunction3 = function(element) {
    //...and so on
};


var _errorMsgFunction = function(msg) {
    $.log("There was an error: " + msg);
    return false;
};


//Public method
var myPublicFunction = function(element,call) {
    //element is jquery object passed through user "click" event
    var userID = element.data('id')
    var userAction = element.data('action');

    //Now... i want to fire _myPrivateFunction1, _myPrivateFunction2, _myPrivateFunction3 in sequence and STOP all processes, and run 
    // _errorMsgFunction if there is an error in any of them.
    //This is how far I've gotten...

    _myPrivateFunction1(userID).then(_myPrivateFunction2(userAction), _errorMsgFunction("Error in _myPrivateFunction2")).then(_myPrivateFunction3(element),_errorMsgFunction("Error in _myPrivateFunction3")).fail(_errorMsgFunction("Error in _myPrivateFunction1"));

};

// Public API
return {
    myPublicFunction: myPublicFunction
};
})();

所以现在我不断收到“_myPrivateFunction2 中的错误”(我出于测试目的强制此错误),但其他函数在继续触发后...它们不会停止。我在这里缺少什么?

最佳答案

您不能共享延迟对象。您应该为每个函数创建一个与延迟不同的 promise 。

这是一些非常简单的示例,为了简单起见,使用了 sycnhronus 函数,尽管 Promise 旨在与异步函数一起使用:

var func1 = function(arg){
    var dfd = jQuery.Deferred();
    if (arg === 0) {
        dfd.resolve('func1 Ok');
    } else {
        dfd.reject('func1 arg != 0');
    }
    return dfd.promise();
}

var func2 = function(arg){
    var dfd = jQuery.Deferred();
    if (arg === 0) {
        dfd.resolve('func2 Ok');
    } else {
        dfd.reject('func2 arg != 0');
    }
    return dfd.promise();
}

var func3 = function(arg){
    var dfd = jQuery.Deferred();
    if (arg === 0) {
        dfd.resolve('func3 Ok');
    } else {
        dfd.reject('func3 arg != 0');
    }
    return dfd.promise();
}

如果函数不依赖于其他函数来进行处理,我们可以使用 jQuery.when 并行执行

// Parallel processing

jQuery.when(func1(1), func2(0), func3(0)).then(function(res1, res2, res3){
    console.log(res1, res2, res3);
}).fail(function(reason){
    console.error(reason); // will fail with reason func1 arg != 0
});

如果它是一个序列处理(据我了解你的问题是),你应该这样做:

// Sequential processing

func1(0).then(function(res1){
    return func2(res1);
}).then(function(res2){
    return func3(res2);
}).then(function(res3){
    // everything ran ok, so do what you have to do...
}).fail(function(reason){
    console.log(reason);
});

上面的代码将失败,原因是:

> func2 arg != 0

如果您要混合并行处理和顺序处理,那么您应该混合使用这两种方法。

<小时/>

免责声明

如我的示例所示,如果 func1func2 有副作用,它们本身不会在 fail() 内撤消。

最佳实践是仅在您绝对确定一切正常时才产生副作用,即在最后一次 then() 调用中。

关于javascript - 如何使用 deferred() 顺序触发 JQuery 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32211793/

相关文章:

javascript - Elfinder:添加关闭按钮

javascript - ES6 promise 执行顺序

javascript - 与nodejs服务器端的时区偏移

JavaScript 正则表达式测试和替换

javascript - 在 Backbone View 中触发 el 事件

javascript - 在窗口和文档上监听滚动事件会导致处理程序之间发生冲突

javascript - JS代码未执行

javascript - 在 Jquery 中如何处理粘贴?

javascript - 如何在label标签中显示javascript变量的值?

jquery - 为一个元素设置多个值