我在Javascript中使用Googles Analytics API。
它们提供了一个获取列表结果的方法,一旦执行完毕,它就会调用带有结果的回调方法。
看起来像这样:
gapi.client.analytics.management.accounts.list().execute(handleAccounts);
...
function handleAccounts(results) {
if (!results.code) {
if (results && results.items && results.items.length) {
// See this code below.
} else {
console.log('No accounts found for this user.')
}
} else {
console.log('There was an error querying accounts: ' + results.message);
}
}
一般来说这太棒了,但是......我需要一个所有子项目的扁平列表,所以我一直这样打电话:
$.each(results.items, function (index, value) {
gapi.client.analytics.management.webproperties.list({ 'accountId': value.Id}).execute(handleWebproperties);
// and so on..
})
问题在于,如果在任何级别你有多个项目,你最终会有多个异步调用射击,我不知道他们什么时候完成了最终列表。
除了写一些内容以跟踪已经拨打了多少电话,然后等待该总数回来。
我怎样才能轻易知道它们何时完成?
感谢。
总结:
用户可以拥有多个帐户,帐户可以拥有多个属性,属性可以包含多个配置文件。
我需要用户所有帐户的所有个人资料。
答案 0 :(得分:0)
解决这个问题的方法是跟踪你已经(或将要制作)的异步调用次数,并在每个响应中收到计数的减量并检查最后一个是否已完成。重要的是确保您有一个强大的错误处理,以防一个响应生成错误并且未成功完成。
你似乎知道这是一个选项,目前还不清楚你为什么不追求这个,但这是解决这个问题的方法。也可以使用jQuery deferreds来跟踪最后一个完成的时间,但是这只是使用一个库来为你计算 - 它在下面仍然基本相同。
答案 1 :(得分:0)
基于我之前写的fork
函数:[{3}}。我会这样做:
var queryFunctions = []
$.each(results.items, function (index, value) {
queryFunctions.push(function(callback){
gapi.client.analytics.management.
webproperties.list({ 'accountId': value.Id}).
execute(callback);
});
})
fork(queryFunctions,function(result){
// This is the final callback, so do processing here
})
fork
的实施就是这样:
function fork (async_calls, shared_callback) {
var counter = async_calls.length;
var all_results = [];
function makeCallback (index) {
return function () {
counter --;
var results = [];
// we use the arguments object here because some callbacks
// in Node pass in multiple arguments as result.
for (var i=0;i<arguments.length;i++) {
results.push(arguments[i]);
}
all_results[index] = results;
if (counter == 0) {
shared_callback(all_results);
}
}
}
for (var i=0;i<async_calls.length;i++) {
async_calls[i](makeCallback(i));
}
}
正如您所看到的,它所做的就是跟踪counter
变量中的调用次数。但它全部封装在一个函数中,因此您可以重用逻辑。另外,我认为它使代码更加整洁。
答案 2 :(得分:0)
您可以使用jQuery Deferred功能执行此类操作。基本上,如果将回调包装在Deferred对象中,则使用$.when(...)
将它们组合在一起。
这样的东西(对你来说最有意义的确切结构将取决于你如何使用它,这段代码假设你需要在每次回调中做一些特定的事情,并知道它们什么时候完成):
var promises = [];
$.each(results.items, function (index, value) {
var deferred = new $.Deferred();
gapi.client.analytics.management.webproperties.list({ 'accountId': value.Id}).execute(function(results) {
handleWebproperties(results);
deferred.resolve();
});
promises.push(deferred.promise());
// and so on...
});
$.when.apply(this, promises).done(function() {
alert("Everything is finished!");
});
注意我只是直接编码到浏览器窗口,所以这可能不是100%正常运行。 :)子>