在Nodejs中递归地处理

时间:2014-01-03 06:15:23

标签: node.js recursion

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

我想在nodejs中以递归方式处理上面数组中的字段名称。由于nodejs异步行为,循环无法正常工作。

1 个答案:

答案 0 :(得分:1)

您需要定义“流程”。如果它是同步的东西,那么显然没什么特别的:

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)

如果在visitor中你想要异步,那么有很多选择。假设您想要进程第一个节点的子节点(并行),然后是节点本身:

// 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')
}

它基本上是相同的代码,但有回调和一些异步流控制代码。当然,您可以使用async包。