0

我在 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..
            })

问题是,如果在任何级别上你有多个项目,你最终会遇到多个异步调用,我不知道他们什么时候都完成了最终列表。

除了写一些东西来跟踪已经打了多少电话,然后等待总数回来。

我怎样才能很容易地知道他们什么时候都完成了?

谢谢。

总之:

一个用户可以有多个帐户,帐户可以有多个属性,属性可以有多个配置文件。

我需要用户所有帐户的所有配置文件。

4

3 回答 3

0

解决此问题的方法是跟踪您已进行(或将要进行)多少次异步调用,并且在每个响应中您收到计数的减量并检查最后一个是否已完成。确保您具有强大的错误处理能力非常重要,以防一个响应生成错误并且未成功完成。

您似乎知道这是一种选择,并且不清楚您为什么不这样做,但这是解决此问题的方法。也可能使用jQuery deferreds来跟踪最后一个完成的时间,但这只是使用一个库来为你计算——它在下面基本上还是一样的。

于 2012-10-08T04:52:52.390 回答
0

基于我fork之前写的函数:Coordinating parallel execution in node.js。我会这样做:

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变量中已进行了多少次调用。但这一切都封装在一个函数中,因此您可以重用逻辑。另外,我认为它使代码更整洁。

于 2012-10-08T05:13:55.040 回答
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% 正常工作。:)

于 2012-10-08T05:24:00.280 回答