如何从递归中的promise中获取值

时间:2017-04-17 18:15:42

标签: javascript node.js recursion

我正在使用NodeJs和Box SDK。

我需要获取目录中所有文件和文件夹的数据,因此我要检查每个文件夹中的子文件夹和文件,将数据保存在数组中,然后再次调用该函数子文件夹。

问题是我无法从递归调用中获取包含所有数据的数组,我无法找出返回或解析函数checkChilds的位置,也无法处理的承诺。

我需要的是一个承诺,一旦for循环完成并且所有堆栈都完成就会解析,这样arrayIds将在完成所有操作后获得所有数据。

我的主目录中的文件夹结构分为预览和生产,所以我也检查它在数组中的位置。

这是我的代码:

var boxUtil = require('../utils/boxUtils')
var boxInstance = boxUtil.getBOXInstance()

exports.script = function (request, response) {
  var accessToken = request.headers.authorization
  var folderId = request.body.folderId
  var userId = request.body.user

  var arrayIds = []

  boxInstance = boxUtil.getBOXInstance()
  if (boxInstance == null) {
    boxUtil.initBOXInstance(userId, function (error, res) {
      if (error) {
        response.status(500)
        return response.send(error.message)
      }
      boxInstance = res
      var box = boxInstance.getBasicClient(accessToken)

      var func = getFolderInfo(folderId, arrayIds, box)
      .then(checkIfPreviewOrProduction)
      .then(insertInPreviewOrProduction)
      .then(iAmRecursive)
      .then(stringLogMe)
      .then(null, console.log)
    })
  } else {
    console.log('RESTART SERVER AND TRY AGAIN PLEASE')
  }
}

function iAmRecursive ([resp, arrayIds, boxInstance]) {
  return new Promise(function (resolve, reject) {
    function checkChilds ([resp, arrayIds, boxInstance]) {
      if (resp.item_collection.total_count > 0) {
        for (var j = 0; j < resp.item_collection.entries.length; j++) {
          if (resp.item_collection.entries[j].type === 'folder') {
            getFolderInfo(resp.item_collection.entries[j].id, arrayIds, boxInstance)
              .then(insert)
              .then(checkChilds)
              .then(null, console.log)
          }
          if (resp.item_collection.entries[j].type === 'file') {
            ifFileChild([resp.item_collection.entries[j], arrayIds, boxInstance])
          }
        }
      } else {
        console.log('no childs were found')
      }
    }
    checkChilds([resp, arrayIds, boxInstance])
  })
}

function stringLogMe (stringifyMe) {
  var text = console.log(JSON.stringify(stringifyMe, null, 2))
  return text
}

function getFolderInfo (folderId, arrayIds, boxInstance) {
  return new Promise(function (resolve, reject) {
    var query = {fields: 'id,name,item_collection,path_collection'}
    boxInstance.folders.get(folderId, query, function (err, resp) {
      if (err) {
        reject(err)
      } else {
        resolve([resp, arrayIds, boxInstance])
      }
    })
  })
}

function getMetadata ([resp, arrayIds, boxInstance]) {
  return new Promise(function (resolve, reject) {
    var fileId = resp.id
    boxInstance.files.getAllMetadata(fileId, function (err, response) {
      if (err) {
        reject(err)
      } else {
        response.name = resp.name
        response.type = resp.type
        resolve([response, arrayIds, boxInstance])
      }
    })
  })
}

function insert ([resp, arrayIds, boxInstance]) {
  return new Promise(function (resolve, reject) {
    if (resp.type === 'file') {
      var newObject = {
        'id': resp.id,
        'name': resp.name,
        'type': resp.type,
        'entries': resp.entries
      }
    } else {
      var newObject = {
        id: resp.id,
        name: resp.name,
        type: resp.type
      }
    }
    arrayIds.push(newObject)
    resolve([resp, arrayIds, boxInstance])
  })
}

function ifFileChild ([resp, arrayIds, boxInstance]) {
  return new Promise(function (resolve, reject) {
    getMetadata([resp, arrayIds, boxInstance])
    .then(insert)
    .then(null, console.log)
  })
}

我的函数iAmRecursive是应该使用promise链中的完整数组解析的函数。

我已经阅读了几个类似的问题,但我无法使用递归调用做任何事情。

如果您需要进一步澄清问题,请告诉我。

1 个答案:

答案 0 :(得分:0)

我稍微重构了这个函数。它现在将收集所有承诺并在解决后立即解决。

function iAmRecursive([resp, arrayIds, boxInstance]) {

  var promises = [];
  for (var j = 0; j < resp.item_collection.entries.length; j++) {
    if (resp.item_collection.entries[j].type === 'folder') {
      promises.push(getFolderInfo(resp.item_collection.entries[j].id, arrayIds, boxInstance)
        .then(insert)
        .then(iAmRecursive)
        .then(null, console.log)
      )
    }
    if (resp.item_collection.entries[j].type === 'file') {
      promises.push(ifFileChild([resp.item_collection.entries[j], arrayIds, boxInstance]));
    }
  }

  return Promise.all(promises);

}

由于评论而进行编辑。你没有解决你的一些承诺。

更改

function ifFileChild ([resp, arrayIds, boxInstance]) {
  return new Promise(function (resolve, reject) {
    getMetadata([resp, arrayIds, boxInstance])
    .then(insert)
    .then(null, console.log)
  })
}

function ifFileChild ([resp, arrayIds, boxInstance]) {
  return getMetadata([resp, arrayIds, boxInstance])
    .then(insert)
    .then(null, console.log)
}

如果您要立即与另一个人一起解决,那么创建一个新的承诺是多余的。但是,如果你不得不,如果有其他异步解析分支,你需要这样的东西:

function ifFileChild ([resp, arrayIds, boxInstance]) {
  return new Promise(function (resolve, reject) {
    if( /* condition*/){
      setTimeout(function(){ resolve("jea"); }, 5000);
    }
    else{
      resolve( getMetadata([resp, arrayIds, boxInstance])
      .then(insert)
      .then(null, console.log)
      )
    }
  })
}

您可以使用它来展平数组:

var flat = (function flatten(result, current){
  return result.concat( Array.isArray(current) ? current.reduce(flatten, []) : current )
})([], array);