【问题标题】:How to call recursively a function that returns a promise?如何递归调用返回承诺的函数?
【发布时间】:2020-01-24 17:31:31
【问题描述】:

我想提取查询 node-js 服务的所有子文件夹和子文档,每次调用它时都会返回一个此类项目的数组。我不知道文件夹树的深度,所以我想递归调用一个函数,该函数最终将返回一个包含所有子文件夹和子文档的数组,从根文件夹列表开始。每个文件夹都由一个文件夹 ID 标识。

所以我做了一个“recPromise(fId)”,它返回一个承诺。在内部,此函数递归调用 recFun(folderId)。我开始从 rootFolder 调用“recPromise(fId)”,因此一旦解决了所有 root-promise,我就可以继续。

rootFolders.map( folderOfRootlevel =>{
    var folderContentPromise = recPromise(folderOfRootlevel.id);
    folderContentPromises.push(folderContentPromise);
})

$q.all(folderContentPromises)
   .then(function(folderContent) { 
      // Do stuff with results.
}

function recPromise(fId){
    return new Promise((resolve, reject) => {
    var items = [];
    function recFun( folderId) {   // asynchronous recursive function
        function handleFolderContent( asyncResult) {  // process async result and decide what to do
        items.push(asyncResult);
        //Now I am in a leaf-node, no child-Folders exist so I return
        if (asyncResult.data.childFolders.length === 0){
              return items;
        }
         else {   
            //child_folders exist. So call again recFun() for every child-Folder     
            for(var item of asyncResult.data.childFolders)  {
               return  recFun(item._id); 
             }                              
        }
    }
    // This is the service that returns the array of child-Folders and child-Docs
    return NodeJSService.ListFolders(folderId).then(handleFolderContent);
   }
  resolve(recFun(fId));
 })
}


It works almost as expected except the loop inside else, where I call again recFun(). 
The NodeJSService will return an array of sub-Folders so I wish to call recfun() for every sub-Folder.
Now, I only get the result of the 1st sub-Folder of the loop, 
which makes sense since I have a return statement there. 
If I remove the return statement and call like this "recFun(item._id);" 
then it breaks the $q.all().

【问题讨论】:

  • 仅供参考,这个循环for(var item of asyncResult.data.childFolders) 毫无意义,因为您在第一次迭代时return。可能您需要删除return
  • @jfriend00 你是对的,返回第一个循环没有意义。我知道我必须在那里删除 return 语句,但如果我这样做,我将无法在 q.all() 中获得所有承诺响应

标签: node.js loops recursion promise


【解决方案1】:

最后,我决定移除 Promise 包装函数并使用 async-await。

        var items = [];
        (async() => {
            for(var item of rootFolders)  {
                await recFun(item.id)
            }
            // Do stuff with items
           // go on form here..
        })()

        function listFolders(folderId) { 
            return new Promise( function( resolve, reject) {
                resolve(FolderService.ListFolders(folderId));  
            })
        }

        async function recFun(folderId) {
            var foldersResponse= await listFolders(folderId);
            items.push(foldersResponse);
            if (foldersResponse.data.childFolders.length === 0){
                return items ;
            }
            else {        
                for(var item of foldersResponse.data.childFolders)  {
                    await recFun(item._id); 
                }    
            }

        }

【讨论】:

    猜你喜欢
    • 2019-05-25
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 2017-05-09
    • 2018-10-11
    • 2018-11-07
    • 2018-01-28
    • 1970-01-01
    相关资源
    最近更新 更多