Javascript 如何使用节点JS中的嵌套/依赖api调用捕获FOR循环结束时的结果

Javascript 如何使用节点JS中的嵌套/依赖api调用捕获FOR循环结束时的结果,javascript,facebook,node.js,asynchronous,facebook-node-sdk,Javascript,Facebook,Node.js,Asynchronous,Facebook Node Sdk,这是我的第一个JavaScript&Node项目,我被卡住了 我正在尝试调用一个RESTAPI,它返回一组Post ID。。。根据检索到的ID集,我尝试调用另一个API,该API返回第一个API中每个ID的详细信息。该代码使用Facebook NodeSDK提供的Facebook API 我遇到的问题是,第二个API在FOR循环中激发…。据我所知,for循环异步执行每个请求…。我可以看到两个查询都在执行,但是我不知道如何捕获第二个for循环的结尾,以便将最终结果返回给用户 下面是代码 expor

这是我的第一个JavaScript&Node项目,我被卡住了

我正在尝试调用一个RESTAPI,它返回一组Post ID。。。根据检索到的ID集,我尝试调用另一个API,该API返回第一个API中每个ID的详细信息。该代码使用Facebook NodeSDK提供的Facebook API

我遇到的问题是,第二个API在FOR循环中激发…。据我所知,for循环异步执行每个请求…。我可以看到两个查询都在执行,但是我不知道如何捕获第二个for循环的结尾,以便将最终结果返回给用户

下面是代码

exports.getFeeds = function(req, res) {

    var posts = [];
    FB.setAccessToken(’SOME TOKEN');
    var resultLength = 0;


     FB.api(
        //ARG #1 FQL Statement
        'fql', { q: 'SELECT post_id FROM stream WHERE filter_key = "others"' },
        //ARG #2 passing argument as a anonymous function with parameter result
        function (result)
           {

               if(!result || result.error) {
                    console.log(!result ? 'error occurred' : result.error);
                    return;
                } //closing if handling error in this block

                    var feedObj
                    console.log(result.data);
                    console.log(result.data.length);

                        for (var i = 0; i<resultLengthj ; i++) {

                        (function(i) {
                            feedObj             = {};
                            FB.api( result.data[ i].post_id,  { fields: ['name', 'description', 'full_picture' ] },
    //                          fbPost is data returned by query
                                function (fbPost) {
                                    if(!fbPost || fbPost.error) {
                                        console.log(!fbPost ? 'error occurred' : result.error);

                                        return;
                                    }
    //                                else
                                        feedObj=fbPost;
                                        posts.push(feedObj);
                            });
                       })(i);
                    }// end for

           }//CLOSE ARG#2 Function

    );// close FB.api Function
注:我需要打电话…。。。res.Sendpost…。我试着在几个地方调用它,但就是不能得到所有的帖子…我已经从上面的代码中删除了控制台语句…这表明数据正在被检索


非常感谢您的帮助和关注……

如果您只是将res.send放在代码中的任何地方,肯定会在您的帖子返回之前收到呼叫

在这种情况下,您要做的是在for循环外声明一个计数器变量,并将其设置为零。然后在for循环中增加它。然后在您的内部回调中(在您的案例中,每个帖子调用一次回调),您将减少计数器并测试它何时达到零。下面,我将这项技术应用到您的代码的编辑版本中,我没有看到feedObj实际上在做什么,也不理解您为什么使用立即调用的函数,所以将两者都删除了-如果我遗漏了什么,请告诉我

var posts = [];
FB.setAccessToken(’SOME TOKEN');
var resultLength = 0;


FB.api(
    //ARG #1 FQL Statement
    'fql', { q: 'SELECT post_id FROM stream WHERE filter_key = "others"' },
    //ARG #2 passing argument as a anonymous function with parameter result
    function (result)
    {

        if(!result || result.error) {
            return;
        } //closing if handling error in this block

        var counter = 0;
        for (var i = 0; i<resultLengthj ; i++) {

            counter++;
            FB.api( result.data[ i].post_id,  { fields: ['name', 'description', 'full_picture' ] },
                function (fbPost) { // fbPost is data returned by query
                    if(!fbPost || fbPost.error) {
                        return;
                    }
                    posts.push(fbPost);
                    counter--;
                    if (counter === 0){
                        // Let's render that page/send that result, etc
                    }
                });

        }// end for

    }//CLOSE ARG#2 Function

);// close FB.api Function

希望这能有所帮助。

实际上,您希望对每个id执行异步映射操作

有一个非常方便的库,用于对集合执行异步操作,名为async,它有一个async.map方法


您当然不需要使用它,但它简化了您的代码。只需在您的项目目录中运行npm安装-保存异步,您就可以开始了。

谢谢barry,我要试试这个。。。要回答你的问题。。。我使用立即调用函数是因为函数中的每个调用都作为异步进程执行,并且I的值不一致,因为时间不同。。。请看例句。。。是的,feedObj是无用的。。。一些调试的剩余部分尝试了你的想法,效果很好。。。添加了立即调用函数,以便为i获取一个好的值,这样我就可以用一个数字为对象编制索引。我理解您对立即调用函数的说法,但我将其分解的原因是,在这种情况下,回调中没有引用i本身,它只在调用结果中引用。data[i].post_id.当然,这里的代码可能是一个缩写版本,在这种情况下,它非常有意义。最重要的是,很高兴它在任何情况下都有帮助!谢谢德里克。。。我看了异步。。。在我使用实用模块之前,我想了解node的结构和原理……我说过我也将尝试异步解决方案……首先,感谢您将我的答案标记为已接受。第二,荣誉和明智的选择,在获取模块之前学习基础知识我认为太多人本能地获取模块,然后缺乏对这些模块实际所做工作的欣赏。第三,如果您打算在某个时候查看libs,我将为它插入一个小插件,除了作为它的用户之外,我与它没有任何关系。我个人认为这是一种更容易处理异步操作的好方法。它不像Async那样受欢迎,但在NPMThanks Barry上也不比Async少多少。。。我认为,如果你能分享你将如何使用Q承诺来实现上述问题,这将是非常有帮助的……只要你能腾出时间……Vishal——我会在有空的时候这样做。问题:FB库是您或您的团队建立的还是NPM上现有的。我之所以这么问,是因为它似乎采用了其他的“标准”节点回调,带有回调错误、数据签名,并且只有回调数据签名。在此期间,我在其他一些问题中提供了一些示例-您可能会发现,作为概述,这些示例很有帮助。我使用facebook node sdk。。。可在NPM。。。我认为它使用了非标准约定,因为模块依赖FB在结果中提供错误。。。这样做的目的是使then模块不会陷入错误代码管理,而是让用户从结果集中解析错误代码。。。将模块升级减少到最低限度
var async = require('async'); 

FB.api(
    'fql', { q: 'SELECT post_id FROM stream WHERE filter_key = "others"' },
    //ARG #2 passing argument as a anonymous function with parameter result
    function (result) {

        async.map(
            result,

            function (item, callback) {
                FB.api(
                    item.post_id, 
                    { fields: ['name', 'description', 'full_picture' ] }, 
                    callback
                );
            },

            function (err, allPosts) {
                if (err) return console.log(err);

                // Array of all posts
                console.log(allPosts);
            }
        );

    }
);