节点js:使递归函数顺序运行/控制流

时间:2017-02-04 22:25:11

标签: node.js recursion

我现在只学习了几天Node。我决定切换到Node的原因是它比php更快,我以前用它作为服务器端语言。最近,我意识到在以递归方式my previous post considering php and VK api发送请求和处理数据时,使用php并不是那么有效。 (顺便说一句,我找到了解决方案)

所以我将我的函数重写为Node,现在由于Node的异步特性,它无法正常工作。

简而言之:此函数必须找到社交网络用户之间的所有间接连接,并使用有关每个找到的间接连接(也是包含字符串的数组)的数据填充数组 connections 每个链成员的数据(即name,second_name和id))。

var find_links = function(n, node1, ports,
  vk, visited, connection, connections, event_count, callback) {
  n+=1;
  if(n<2) { // I don't want to go too far with my recursion. I keep track of it
    // vk.request just send a request to api and gets a list of friends of a user with user_id: node1 

    vk.request('friends.get', {'user_id' : node1, 'fields' : 'domain, first_name'}, function(_o) { 
      // when we get response it may be either response or 'error' if user has deleted their account

    if('response' in _o) { // just checking if we have response

        for (var item of _o['response']['items']) {
          for (var port of ports['response']['items']) {

            if(port['id'] == item['id']) {
              data = item['first_name'] + ' ' + item['last_name'] + ' ' + item['id']; // info about user
              connection.push(data);
              connections.push(connection);
              connection.pop();
              break;
            }
            else {
              if (!visited.present(item['id'])) { // if we haven't encountered this user before
                data = item['first_name'] + ' ' + item['last_name'] + ' ' + item['id']; // info about user
                connection.push(data);
                visited.push(item['id']); // we add user_id to visited array 
                // recursion 
                find_links(n, item['id'], ports, vk, visited, connection, connections, event_count, console.log);
                connection.pop();
              }
            }
          }

        }
        if (n == 1) {
          callback("conn is "+connections);
        }
      }
      else {
        return 1;
      }
    });
  }
  else { // if n == 2, i check only friends of current user and return 
    vk.request('friends.get', {'user_id' : node1, 'fields' : 'domain, first_name'}, function(_o) {
      if('response' in _o) {
        for(item_ of _o['response']['items']) {
          for(var arg_ of ports['response']['items']) {
            if (arg_['id'] === item_['id'] && !visited.present(item_['id'])) {
              data = item_['first_name'] + ' ' + item_['last_name'] + ' ' + item_['id'];
              connection.push(data); // add data about user to connection
              connections.push(connection);
              connection.pop();
              break;
            }
            else {
              connection.pop();
            }
          }
        }
      }
      return 1;
    })
  }
}

因此,当我记录 connections 数组时,必须包含有关找到的所有链的数据,我得到此,,,,,,,,,,,,,,,,。物品只是没有被推到阵列,是吗?

那么,如何让我的代码顺序循环运行并在继续之前等待递归函数完成?

当我请求朋友时,来自VK的回复如下:

{ response:
    { count: 67,
      items:
       [ { id: 6248811,
           first_name: 'Екатерина',
           last_name: 'Федорова',
           domain: 'k.fedorova' },
         { id: 8102967,
           first_name: 'Роман',
           last_name: 'Соколинский',
           domain: 'majestyk',
           hidden: 1 },
           .....
    ]
    }
}

1 个答案:

答案 0 :(得分:0)

您需要的是async库。

    var async = require('async');

    function myRecursiveFunc(arr, results, fcb) {
        async.eachSeries(arr,
        function(item, cb) {
            doSomethingAsync(function() {
            ...
            // modify results arr here
            ...
            // do we have a new array to process?
            if(...) {
                myRecursiveFunction(newArr, results, cb);
            }else{
                // call next iteration
                cb();
            }
            });
        },
        function(err) {
            fcb(err);
        }
        );

    }

    var results = [];
    var arr = [...];
    myRecursiveFunction(arr, results, function(err) {
        if(err) {
            console.trace(err);
        }
        console.log(results);
    });