0

I've been learning Node for only few days now. The reason why I decided to switch to Node is that it's way faster than php, which I used to use as a server side language. Recently, I realized that using php is not that effective when it comes to sending requests and processing data in a recursive manner my previous post considering php and VK api. (By the way, I found a solution to that one)

So I rewrote my function to Node and now it doesn't work properly due to the async nature of Node.

To put it short: this function must find all the indirect connections between users of a social network and fill an array connections with data about each found indirect connection (which is also an array that contains strings of data about each chain member (i.e. name, second_name and 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;
    })
  }
}

So, when I log connections array which must contain data about all the chains found, I get this ,,,,,,,,,,,,,,,,. Items just aren't pushed to the array, are they?

So, how can I get my code run in a loop sequentially and wait for the recursive function to finish before proceeding?

Response from VK when I request friends looks like this:

{ response:
    { count: 67,
      items:
       [ { id: 6248811,
           first_name: 'Екатерина',
           last_name: 'Федорова',
           domain: 'k.fedorova' },
         { id: 8102967,
           first_name: 'Роман',
           last_name: 'Соколинский',
           domain: 'majestyk',
           hidden: 1 },
           .....
    ]
    }
}
7
  • This code is a little confusing... Could you provide a stripped down version? Why do you push and pop when you can just push the data directly? You can however look at using block scope variables (let myvar = something). Those are not affected by your outer scope and are very handy in async loops. And callbacks are not really how you do it these days (look at promises, for instance github.com/kriskowal/q) Commented Feb 4, 2017 at 22:39
  • @Rienk What do you mean by pushing the data directly? I need to push and pop data to and from arrays, because in this way I can keep track of which users I've visited. For now, I see it as the best way possible to do this. Commented Feb 4, 2017 at 22:52
  • ok, it is a bit confusing. Why don't you create an object for visited users? => var connections = {}; connections[userid] = some connection data; And after that to check if allready visited: if (typeof connections[otheruserid] === 'undefined'){connections[otheruserid] = some connection data;}else{continue;}; Commented Feb 4, 2017 at 23:12
  • @Rienk I already have an object called visited with custom method 'present' which checks if an item is in array. I push user_ids to this object: so the function never processes visited users again. And I have object connection to store info about one indirect connection, and connections object which stores several connection. I need connections to later be able to render all indirect connections found Commented Feb 4, 2017 at 23:17
  • ok, I think I see an issue (not all I think but hey..). You are calling find_links recursively, but I think you need to return it within your function (return find_links(params);). Commented Feb 4, 2017 at 23:27

1 Answer 1

0

What you need is async library.

    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);
    });
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.