Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

process recursively in Nodejs

[
{
    name: 'test1',
    fields: [
        {
            name: 'test11',
            fields: [
                {
                    name: 'test111',
                    fields: [
                        {
                            name: 'test1111'
                        }
                    ]
                }
            ]
        }
    ]
},
{
    name: 'test2',
    fields: [
        {
            name: 'test21'
        },
        {
            name: 'test22'
        }
    ]
}

]

I want to process fields name in the above array, recursively in nodejs. Loop is not working due to nodejs asynchronous behavior.

like image 874
Rohit Avatar asked Jan 03 '14 06:01

Rohit


People also ask

What is recursion in node JS?

Recursion is a process of calling itself. A function that calls itself is called a recursive function. The syntax for recursive function is: function recurse() { // function code recurse(); // function code } recurse(); Here, the recurse() function is a recursive function.

What is recursive in JS?

Recursion is when a function calls itself until someone stops it. If no one stops it then it'll recurse (call itself) forever. Recursive functions let you perform a unit of work multiple times.

How do you create a recursive function?

Writing a recursive function is almost the same as reading one: Create a regular function with a base case that can be reached with its parameters. Pass arguments into the function that immediately trigger the base case. Pass the next arguments that trigger the recursive call just once.

Is recursion more efficient than iteration?

Strengths: Iteration can be used to repeatedly execute a set of statements without the overhead of function calls and without using stack memory. Iteration is faster and more efficient than recursion. It's easier to optimize iterative codes, and they generally have polynomial time complexity.


1 Answers

You need to define "process". If it is something synchronous, nothing special, obviously:

function visit (visitor, obj) {
  if (Array.isArray(obj)) return obj.forEach(visit.bind(null, visitor))
  if (Array.isArray(obj.fields)) obj.fields.forEach(visit.bind(null, visitor))
  visitor(obj)
}

function visitor (obj) {
  console.log(obj.name)
}

visit(visitor, data)

If in visitor you want to something asynchronous, there are a lot of options. Assuming that you want process first node's children (in parallel) and then the node itself:

// the order of arguments is weird, but it allows to use `bind`
function visit (visitor, callback, obj) {
  var array
  if (Array.isArray(obj)) array = obj
  if (Array.isArray(obj.fields)) array = obj.fields

  if (!array) return visitor(obj, callback)

  // number of pending "tasks"
  var pending = array.length
  var done = false

  function cb () {
    // ensure that callback is called only once
    if (done) return
    if (!--pending) {
      done = true

      // after all children are done process the node itself
      if (!Array.isArray(obj)) return visitor(obj, callback)

      //if the whole node is array
      callback()
    }
  }

  array.forEach(visit.bind(null, visitor, cb))
}

function visitor (obj, callback) {
  process.nextTick(function () {
    console.log(obj.name)
    callback()
  })
}

visit(visitor, after, data)

function after () {
  console.log('all done')
}

It's basically the same code, but with callbacks plus some async flow control code. Of course, you can use async package instead.

like image 151
vkurchatkin Avatar answered Sep 30 '22 19:09

vkurchatkin