【问题标题】:How to get a value from a promise within a recursion如何从递归中的 Promise 中获取值
【发布时间】:2023-03-07 13:01:01
【问题描述】:

我正在使用 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.all
  • 感谢您的宝贵时间!我只是编辑了代码以使其更简单。问题是,我怎么知道递归函数什么时候会收集到所有的名字?因为现在我的函数 iAmRecursivecheckChilds 没有返回或解析任何结果。我已经尝试过多次解决承诺,但没有奏效。我应该返回checkChilds 吗?同时解决?

标签: javascript node.js recursion


【解决方案1】:

我稍微重构了函数。它现在将收集所有的 Promise 并在它们全部解决后解决。

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);

}

由于 cmets 而编辑。您没有兑现您的某些承诺。

改变

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

如果您要立即与另一个promise 解决它,那么创建一个新promise 是多余的。但是如果你必须这样做,例如,如果有其他异步解析分支,你会想要这样的:

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);

【讨论】:

  • 感谢您的宝贵时间!我使用return 语句运行代码,它现在所做的是检查前 4 个文件夹,当它找不到更多子文件夹时,它会记录 no childs were found 并停止整个函数只是停止那个堆栈。
  • else 分支也必须解决。看看它现在是否有效。
  • 恐怕还是不行,看来我们解决整个函数太早了。
  • 代码现在运行得更好了!但是响应不对,我得到: [ [ [ [ [], [], [ null, null ] ], [], [ null, null ] ] ], [ [ [ [], [], [ null, null ] ], [], [ null, null, null, null, null, null ] ] ] ] 当我期望一个平面数组时: [ { "foo": "bar" }, { "foo": "酒吧”}]
  • 知道为什么会这样吗?
猜你喜欢
  • 2018-05-16
  • 2021-04-29
  • 2020-09-20
  • 2020-04-30
  • 1970-01-01
  • 2018-08-01
  • 2020-07-20
  • 2021-08-04
  • 1970-01-01
相关资源
最近更新 更多