【问题标题】:problems with waiting for multiple deferred function calls to finish等待多个延迟函数调用完成的问题
【发布时间】:2012-09-19 02:45:36
【问题描述】:

我正在尝试使用 node-facebook-sdk 使用 Node.JS 进行 FB 图形 API 调用

我想从所有用户朋友那里获取提要数据。 FB graph API 每次批量请求只允许 50 个朋友,所以我正在做一系列批量 FB.api() 调用。

我正在尝试将 FB.api() 调用存储在一个数组中,然后使用 jQuery when() 调用延迟函数。

问题:

1) 我传递给 .done() 函数的函数过早执行。 2) console.log(feed) 在 .done() 之后执行,据我所知这不应该发生。

$ = require('jQuery');


//maximum batch size request is 50. use 2-D array to store in buckets of 50 friends each.
                var numFriends = friends.data.length;
                var batch = [];
                var deferred = [];//array to hold all the requests
                var feed_dump = [];//where we collect all the feed data

            //initialize a bucket for each set of 50 friends
            for (var i = 0, ii = numFriends / 50; i < ii; i++) {batch.push([]);}

            //put corresponding requests in in buckets.
            for (var i = 0; i < numFriends; i++) {
                batch[Math.floor(i/50)].push({ method: 'get', relative_url: friends.data[i].id + '/feed?since=' + '-1 month'});//not sure if the date format will work user.last_updated
            }

            //make the multiquery request for each bucket
            for (var i in batch) {
                var bucket = batch[i];
                //nested FB api call

                deferred.push(FB.api('', 'post', {'batch' : bucket}, function(res){//res = array 50 friend feeds
                        if (!res || res.error) {
                            console.log(!res ? 'error occurred' : res.error); return;
                        }
                        for (var j in res) {
                            var feed = JSON.parse(res[j].body);
                            console.log(feed);
                            feed_dump.push(feed);//feed for each friend appeneded to dump
                        }
                }));
            }

            console.log('this should show up before graph api requests are made.');

            //jQuery when() function.
            $.when.apply(null, deferred).done(function() {
                console.log('hopefully feed_dump has been updated...');
                PySocket.emit('update_user_graph',JSON.stringify(feed_dump));
            });

如何正确推迟批处理 FB.api() 请求?另外,如果有人能想到更好的方法,请告诉我;我对异步 javascript 没有那么丰富的经验。

我想我的问题的一个更简单的形式是:如何等待多个回调函数完成?

非常感谢。

【问题讨论】:

  • 你不应该把你推送的“延迟”内容包装在一个函数中,所以它只会被 $.when.apply 调用吗?

标签: jquery node.js facebook-graph-api


【解决方案1】:

编辑:封装的回调计数递减:http://jsfiddle.net/3L9zc/32/

function BatchAPICalls(){
    var calls = [];
    var self = this;

    self.push = function(){
        var args = [];

        for(var i = 1; i < arguments.length - 1; i++)
            args.push(arguments[i]);

        calls.push({
            fn: arguments[0],
            callback: arguments[arguments.length - 1],
            args: args
        });        
    };

    self.start = function(callback){
        var callbacksLeft = calls.length;

        function batchCallback(){
            callbacksLeft--;
            if(callbacksLeft == 0)
                callback();
        }

        for(var i = 0; i < calls.length; i++){

            var call = calls[i];

            var batchItemCallback = function(){
                call.callback.apply(this, arguments);
                batchCallback();
            };

            call.fn.apply(this, call.args.concat([batchItemCallback]));            
        }
    };
}



var numFriends = friends.data.length;
var batch = [];
var feed_dump = [];

for (var i = 0, ii = numFriends / 50; i < ii; i++) {
    batch.push([]);
}

for (var i = 0; i < numFriends; i++) {
    batch[Math.floor(i/50)].push({ 
        method: 'get', 
        relative_url: friends.data[i].id + '/feed?since=' + '-1 month'
    });
}

function done() {
    console.log('hopefully feed_dump has been updated...');
    PySocket.emit('update_user_graph',JSON.stringify(feed_dump));
}    

var batchCalls = new BatchAPICalls();

for (var i in batch) {
    var bucket = batch[i];

    batchCalls.push(FB.api, 'call #' + i, 'post', {'batch' : bucket}, function(res){

        if (!res || res.error) {
            console.log(!res ? 'error occurred' : res.error); return;
        }
        for (var j in res) {
            var feed = JSON.parse(res[j].body);
            console.log(feed);
            feed_dump.push(feed);//feed for each friend appeneded to dump
        }
    });
}

console.log('this should show up before graph api requests are made.');

batchCalls.start(done);

【讨论】:

  • 在我的旧代码中,当我将它们添加到延迟数组时,这些函数没有执行(我在填充数组后设置了一个断点并等待了一段时间)。
  • 我看到了,FB.api 调用是异步的,因此不能保证它会立即执行,但调用会进行。
  • 正确 - 所以 $.when() 调用只是一个带有回调的简单函数的包装器。但我正在尝试寻找是否有办法等待 FB.api() 调用的回调完成。
  • @ejang :如果我的新解决方案有效,请告诉我(查看编辑)
  • 计数器递减是一种骇人听闻的方法——我一直在寻找一种更优雅的方法,也许包装在一个库中。观看柜台的检查机制将在哪里进行?如果我使用 while() 循环,它会阻塞系统。如果我使用 setInterval,我可能会等待比我应该等待的时间更长。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-23
  • 1970-01-01
  • 2014-06-21
相关资源
最近更新 更多