本文旨在解决在使用 promise.all() 方法时,如何正确地返回包含两个对象的嵌套对象。通过示例代码,我们将展示如何处理 Promise 嵌套,并确保在返回最终结果之前,所有异步操作都已完成,避免返回空的 JSON 对象。
在使用 Promise.all() 处理异步操作时,经常会遇到需要返回包含多个对象信息的场景。例如,我们需要从数据库中获取多个用户的信息,并将每个用户的信息与其关联的历史数据组合成一个对象返回。如果处理不当,可能会导致返回的对象中包含未解析的 Promise,从而得到空的 json 对象。
问题分析
问题的核心在于 Promise.all() 内部的异步操作没有完全完成就被返回了。在提供的代码片段中,users.findOne() 返回的是一个 Promise 对象,如果没有使用 await 等待其解析完成,直接将其作为对象属性返回,那么该属性的值将是一个 Promise 对象,而不是实际的数据。当 NextResponse.json() 对其进行序列化时,Promise 对象会被转换为空的 JSON 对象。
解决方案
解决这个问题的方法是确保在返回结果之前,所有的 Promise 对象都已解析。这可以通过以下两种方式实现:
-
使用 await 关键字:
在 Promise.all() 的 map 函数中,使用 await 关键字等待 users.findOne() 返回的 Promise 对象解析完成。这样,us 变量将包含实际的用户数据,而不是一个 Promise 对象。
import users from "@/models/users"; import { NextResponse } from "next/server"; import bcrypt from "bcryptjs"; import dbConnect from "@/util/mongodb"; export async function GET(req, { params }) { await dbConnect(); try { const data = await users.findOne({ username: params.id }, { pin: 0 }); const history = await Promise.all( data.history.map(async (user) => { const us = await users.findOne( { _id: user.id }, { firstname: 1, username: 1, lastname: 1 } ); return { user: us, amount: user.amount }; }) ); return NextResponse.json(history, { status: 200 }); } catch (err) { return NextResponse.json(err, { status: 500 }); } }
注意: 在 map 函数中使用 await 关键字时,需要确保 map 函数本身被声明为 async 函数。
-
显式地使用 .then() 方法:
虽然 await 关键字更加简洁易懂,但也可以使用 .then() 方法来处理 Promise 的解析。
const history = await Promise.all( data.history.map((user) => { return users.findOne( { _id: user.id }, { firstname: 1, username: 1, lastname: 1 } ).then(us => { return { user: us, amount: user.amount }; }); }) );
这种方法通过 .then() 方法指定了 Promise 对象解析完成后要执行的回调函数,确保在返回结果之前,us 变量包含实际的用户数据。
总结
在使用 Promise.all() 处理异步操作并返回嵌套对象时,务必注意确保所有的 Promise 对象都已解析。可以使用 await 关键字或 .then() 方法来等待 Promise 对象解析完成,避免返回包含未解析 Promise 的对象,从而得到正确的 JSON 响应。 此外,良好的错误处理机制也是必不可少的,在 try…catch 块中捕获并处理异常,可以提高代码的健壮性。
评论(已关闭)
评论已关闭