[
{
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With