Javascript 混合回调函数队列和jQuery延迟
我正在尝试创建一个函数队列,以调用它来返回自动完成结果。其中一些是我通过$.getJSON调用自己构造的函数,还有一些是由外部开发人员使用提供给我的 例如,这里提供了一个假的。我不知道它是否真正异步,或者何时调用回调:Javascript 混合回调函数队列和jQuery延迟,javascript,jquery,jquery-ui,jquery-ui-autocomplete,jquery-deferred,Javascript,Jquery,Jquery Ui,Jquery Ui Autocomplete,Jquery Deferred,我正在尝试创建一个函数队列,以调用它来返回自动完成结果。其中一些是我通过$.getJSON调用自己构造的函数,还有一些是由外部开发人员使用提供给我的 例如,这里提供了一个假的。我不知道它是否真正异步,或者何时调用回调: var providedFunction = function(search, response) { setTimeout(function() { var arr = ['One', 'Two', 'Demo Custom']; res
var providedFunction = function(search, response) {
setTimeout(function() {
var arr = ['One', 'Two', 'Demo Custom'];
response($.grep(arr, function (s) { return s.indexOf(search) === 0; }));
},5000);
};
然后我想将它与其他一些$.getJSON调用结合起来,直到整个列表完成后才继续:
var searchTerm = "Demo";
var allResults = [];
var functionQueue = [];
functionQueue.push(
$.getJSON( 'http://ws.geonames.org/searchJSON?featureClass=P&style=short&maxRows=50&name_startsWith=' + searchTerm)
.success( function(data) {
$.each(data.geonames, function(i,d) {
allResults.push(d.name); });
})
);
functionQueue.push(
providedFunction(searchTerm, function(data) {
allResults.push.apply(allResults, data);
})
);
// wait for all asyc functions to have added their results,
$.when.apply($, functionQueue).done(function() {
console.log(allResults.length, allResults);
});
问题是,$.when不会等待提供的函数完成。一旦所有$.getJSON调用完成,它就会返回。很明显,我没有正确连接提供的函数,但我不知道如何操作。如果您想使用$。当您想创建一个延迟数组时,您可以像这样调用提供的函数:
functionQueue.push( (function(){
var df = new $.Deferred();
providedFunction(searchTerm, function(data) {
allResults.push.apply(allResults, data);
df.resolve();
})
return df;
})()
);
providedFunctionAsDeferred = castAPItoDeferred(providedFunction);
functionQueue.push(
providedFunctionAsDeferred(searchTerm)
.success( function(data) {
allResults.push.apply(allResults, data);
})
);
当然,如果您真的很喜欢,您可以使用这个方便的实用工具来铸造基于回调的API,以承诺/延迟的API:
function castAPItoDeferred(origFunction){
return function(){
var df = new $.Deferred(),
args = Array.prototype.slice.call(arguments, 0);
// assume that the API assumes the last arg is the callback
args.push(function(result){
df.resolve(result);
});
try {
origFunction.apply(null, args);
} catch(e) {
df.reject(e);
}
return df;
}
}
这会让你做一些像这样的好事:
functionQueue.push( (function(){
var df = new $.Deferred();
providedFunction(searchTerm, function(data) {
allResults.push.apply(allResults, data);
df.resolve();
})
return df;
})()
);
providedFunctionAsDeferred = castAPItoDeferred(providedFunction);
functionQueue.push(
providedFunctionAsDeferred(searchTerm)
.success( function(data) {
allResults.push.apply(allResults, data);
})
);
最后一条警告-如果您选择第二条路线,请记住,如果在对象上调用API函数(如myApi.doSomeAsyncThing
),请挂接/绑定API函数
最后,使用$.when的一种替代方法是手动跟踪,可能使用计数器。e、 g.,:
var counter = 2; // set your number of ops here
var checkIfFinished = function(){
if(--counter === 0) {
triggerAllEventsCompleteFunc(); // replace this with your desired action
}
}
// call checkIfFinished in all your callbacks
providedFunction
不是延迟对象,因此$。当
假设它立即被解决时。@KevinB谢谢,但我不知道如何将它转换为延迟对象,因为我无法控制它的定义(它被传递给我)关于“如果你想使用$.when”:有没有更好的方法来调用任意长的.getJSON调用+这些其他自定义函数的混合调用,并且在所有调用完成之前不继续?编辑我的答案以添加这一点,这实际上取决于您的具体情况以及您事先知道的具体情况/您的代码需要有多灵活。