我有一个处理程序(回调),一个要处理的对象和四个函数,它们将数据收集到对象。在我的情况下,我希望异步调用四个数据检索器,当完成所有四个的执行时,处理结果对象(类似于以下内容):
var data = {};
function handle (jsObj) {}
// data retrieving
function getColorData () {}
function getSizeData () {}
function getWeightData () {}
function getExtraData () {}
data.color = getColorData();
data.size = getSizeData();
data.weight = getWeightData();
data.extra = getExtraData();
handle( data );
当然,此代码无法正常运行。如果我链接数据检索功能,它们将被一个接一个地调用,对吧? 所有四个函数都应该异步调用,因为它们被执行的时间太长而无法逐个调用它们。
更新
感谢大家的建议!我更喜欢$.Deferred()
,但我觉得让它按照我需要的方式工作有点困难。我需要的是异步制作view
,这需要四种数据(extraData
,colorData
,sizeData
& weightData
)我有三种对象:App
,Utils
& Tools
。
只是一个小描述:view
是通过调用App.getStuff
传递App.handleStuff
作为回调来创建的。 App.getStuff
正文中的回调仅被称为$.when(App.getExtraData(), App.getColorData(), App.getSizeData(), App.getWeightData())
。之前Utils.asyncRequest
传递Tools.parseResponse
作为回调被调用。
那么,现在问题是我应该在每个App.get*Data()
内创建四个延迟对象,还要从每个return deferred.promise()
创建deferred.resolve()
?
我应该在订单的最后一个函数中Tools.parseResponse
(在我的示例中为App.getExtraData
var view,
App,
Utils = {},
Tools = {};
// Utils
Utils.asyncRequest = function (path, callback) {
var data,
parseResponse = callback;
// do something with 'data'
parseResponse( data );
};
// Tools
Tools.parseResponse = function (data) {
var output = {};
// do something to make 'output' from 'data'
/* So, should the deferred.resolve() be done here? */
deferred.resolve(output);
/// OR deferred.resolve();
/// OR return output;
};
// App
App = {
// Only one method really works in my example
getExtraData : function () {
var deferred = new jQuery.Deferred();
Utils.asyncRequest("/dir/data.txt", Tools.parseResponse);
return deferred.promise();
},
// Others do nothing
getColorData : function () { /* ... */ },
getSizeData : function () { /* ... */ },
getWeightData : function () { /* ... */ }
};
App.getStuff = function (callback) {
$.when(
App.getExtraData(),
App.getColorData(),
App.getSizeData(),
App.getWeightData()
)
.then(function (extraData, colorData, sizeData, weightData) {
var context,
handleStuff = callback;
// do something to make all kinds of data become a single object
handleStuff( context );
});
};
App.handleStuff = function (stuff) { /* ... */ };
/// RUN
view = App.getStuff( App.handleStuff );
)吗?
jQuery.Deferred()
我没想到上面示例中的代码可以正常工作,它仅用于说明目的。
我一直试图解决这个问题很长一段时间,但仍然没有结果。不幸的是,{{1}}的文档和围绕此问题的讨论对我没有帮助。所以,我会非常高兴和乐于助人或建议。
答案 0 :(得分:0)
我认为您正在寻找的是Promises / Deferreds。
有了承诺,你可以写下这样的东西:
when(getColorData(), getSizeData(), getWeightData(), getExtraData()).then(
function (colorData, sizeData, weightData, extraData) {
handle(/*..*/);
}
)
get*Data()
函数将返回他们在同步调用完成时履行的承诺。
例如:
function getData() {
var promise = new Promise();
doAjax("getData", { "foo": "bar" }, function (result) {
promise.resolve(result);
});
return promise;
}
when
只是计算数字参数,如果它的所有承诺都已解决,它将使用承诺的结果调用then
。
jQuery有一个OK实现:http://api.jquery.com/jQuery.when/
答案 1 :(得分:0)
从概念上讲,您将使用一个在每个异步调用完成时递增的计数器。在所有异步调用增加计数器之后,主调用者应该继续。
答案 2 :(得分:0)
我可以为这种情况建议的是这样的。 写一个像这样的函数
var completed = 0;
checkHandler = function() {
if(completed == 4) {
handle(data);
}
}
已完成的是您必须收到的正回调数。 只要每个函数都收到回调,您就可以递增“completed”计数器并调用checkHandler函数。你已经完成了!
示例中的
function getColorData() {
$.get('ajax/test.html', function(data) {
completed++;
checkHandler();
});
}