JS递归函数未执行完时return为何提前返回空images数组
问题根因
返回值为空是典型的异步逻辑未等待导致的:
callMsGraph是返回Promise的异步函数,所有API请求的回调逻辑都会进入JS事件队列排队,不会阻塞同步代码执行- 现有代码执行到
return images时,res.then()触发的遍历逻辑、start函数内所有递归的Graph API请求都还没执行到images.push()的步骤,此时返回的只是初始化的空数组 - 你在
start内部的console.log能看到数据,是因为这些日志在异步回调里执行,时机晚于函数return,和你拿到的返回值不是同一个时间点的状态 - 原代码没有对递归、循环里的多个异步Promise做聚合等待,外层根本无法获知遍历什么时候完成
修复方案
把整个流程改成async/await写法,所有异步操作全部等待完成后再返回结果,修复后代码如下:
shelfdb.data = async (accessToken) => { const token = accessToken; const rootEndpoint = 'https://graph.microsoft.com/v1.0/sites/webgroup.sharepoint.com,23e7ef7a-a529-4dde-81ba-67afb4f44401,0fa8e0f7-1c76-4ad0-9b6e-a485f9bfd63c/drive/items/01GNYB5KPQ57RHLPZCJFE2QMVKT5U3NYY3/children' const images = []; async function start(node) { if (!node.value) return; // 等待当前层级所有子节点请求、递归遍历全部完成 await Promise.all(node.value.map(async (child) => { const childEndpoint = `https://graph.microsoft.com/v1.0/sites/webgroup.sharepoint.com,23e7ef7a-a529-4dde-81ba-67afb4f44401,0fa8e0f7-1c76-4ad0-9b6e-a485f9bfd63c/drive/items/${child.id}/children`; const childRes = await callMsGraph(token, childEndpoint); // 当前节点下是图片目录,收集所有图片 if (childRes.value.length > 0 && 'image' in childRes.value[0]) { childRes.value.forEach(imgChild => { images.push({ name: imgChild.name, job: imgChild.parentReference.path.split("/")[6], path: imgChild.webUrl }); }); return; } // 非图片目录,递归向下遍历 await start(childRes); })); } // 等待根节点请求、全量遍历完成 const rootRes = await callMsGraph(token, rootEndpoint); await start(rootRes); return images; };
调用注意
修改后的data函数是异步函数,返回值为Promise,调用时需要用await或者.then()接收结果,路由调用示例:
// 路由处理函数需要加async关键字 router.get('/your-image-path', async (req, res) => { const imageList = await shelfdb.data(req.accessToken); res.json(imageList); })
内容的提问来源于stack exchange,提问作者TabulaRasa
相关产品推荐
相关产品推荐

