我真的很难理解 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
如果您要混合并行处理和顺序处理,那么您应该混合使用这两种方法。
<小时/>免责声明
如我的示例所示,如果 func1
或 func2
有副作用,它们本身不会在 fail()
内撤消。
最佳实践是仅在您绝对确定一切正常时才产生副作用,即在最后一次 then()
调用中。
关于javascript - 如何使用 deferred() 顺序触发 JQuery 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32211793/