Strapi中map遍历调用异步查询返回Pending Promise的问题求助
问题根源定位
你打印的books始终是pending状态Promise,和getBooks内部的返回写法关系不大,核心问题出在调用环节:
- 你在map的同步回调里调用
this.getBooks(data.id)时,没有加await。同步逻辑执行到console.log这一行时,数据库查询的异步操作才刚被发起,根本还没拿到结果,自然只能拿到还没走完流程的pending Promise对象 - 你修改
getBooks时额外包裹的Promise.resolve(books)属于完全冗余的代码,对解决问题没有任何帮助。
补充说明:async函数本身的返回值就会被自动包装成Promise对象,当函数内部的异步操作执行完成后,这个Promise会自动转为已完成状态。不管你是直接return数据库查询结果,还是先await拿到结果再手动
Promise.resolve返回,最终对外暴露的行为完全没有区别。
正确实现方式
针对Strapi接口处理的通用场景(需要等所有关联数据查询完成后,再组装成完整的响应返回给前端),可以用Promise.all配合异步map回调的写法,完整修改后的可运行代码如下:
async search(ctx) { const authors = [ { id: 1, name: "author 1" }, { id: 2, name: "author 2" }, ] // 收集所有作者关联的书籍查询Promise,统一等待全部执行完成 const authorListWithBooks = await Promise.all( // map的回调必须声明为async,才能在内部使用await语法 authors.map(async (data) => { // 必须在调用getBooks的位置加await,才能拿到真实的数据库查询结果 const books = await this.getBooks(data.id) console.log(books) // 这里会正常打印完整的书籍查询数组 // 可按需把查询到的books挂载到作者对象上,做后续逻辑处理 return { ...data, books } }) ) // 所有数据查询完成后,再正常返回接口响应 ctx.body = authorListWithBooks }, // 不需要额外包裹Promise.resolve,保留最简洁的写法即可 getBooks: async function (authorId) { return strapi.query('books').find({ userId: authorId }) }
关键注意事项
Array.prototype.map是同步执行方法,本身不会等待内部的异步操作走完。如果不配合Promise.all收集所有Promise并统一await,外层的接口逻辑会提前执行,不等异步查询完成就返回响应,很容易出现响应数据缺失的问题- 只要是调用async函数,想要拿到最终的解析值,就必须在调用位置加
await,否则无论被调用的async函数内部写的多么复杂,你拿到的永远是当前未完成的Promise实例 - 不要在async函数的返回值位置手动包裹
Promise.resolve,这类写法没有任何实际作用,反而会增加无意义的代码层级
内容的提问来源于stack exchange,提问作者Emerald
相关产品推荐
相关产品推荐

