Javascript承诺链地狱
我不知道如何解决承诺链的问题。我的代码摘要:我为特定用户执行mongoose查询,获取他的CarID,然后查询每辆车的详细信息,并通过JSON响应返回这些详细信息Javascript承诺链地狱,javascript,node.js,Javascript,Node.js,我不知道如何解决承诺链的问题。我的代码摘要:我为特定用户执行mongoose查询,获取他的CarID,然后查询每辆车的详细信息,并通过JSON响应返回这些详细信息 let carsDetails = []; User.findById(userId) .then(user => { const carIds = user.carsDetails; carIds.forEach((carId) => { Car.findById(c
let carsDetails = [];
User.findById(userId)
.then(user => {
const carIds = user.carsDetails;
carIds.forEach((carId) => {
Car.findById(carId)
.then(car => {
console.log(car);
carsDetails.push(car);
})
.catch(err => { throw err; });
});
return res.status(200).json({ data: carsDetails });
})
.catch(error => {
throw error;
});
问题是没有汽车被实际推到carsDetails.pushcar上的carsDetails数组上;行,因为它在填充数组之前跳转到return语句。是否有一种解决方法可以执行这些查询并以数组、对象…的形式返回结果。。。?我也尝试过用自制的AsyncForEach语句以AsyncWait形式编写所有内容,但这对我没有帮助。有什么建议吗?我已经试过了,但没有解决问题。谢谢 您需要收集Car.findbyidcandcalls的承诺,并使用Promise.all等待所有承诺,然后再回复。您可以使用array.map将每个ID映射到Car.findById中的承诺
您需要收集Car.findbyidcandcalls的承诺,并使用Promise.all等待所有承诺,然后再回复。您可以使用array.map将每个ID映射到Car.findById中的承诺 await/async是一种方式,使用await/async您可以使用常规的。。。而不是forEach 异步函数getCardDetails{ 让carsDetails=[]; let user=await user.findByIduserId; const carIds=user.carsDetails; 让龋齿的龋齿{ let car=等待car.findbyidcrad 控制台、行车记录仪; carsdeails.pushcar; } 返回res.status200.json{ 数据:carsDetails }; } 或者你用Promise.all和map代替。。。的 这两种解决方案略有不同。带有映射的第二个版本将立即将所有请求发送到DB,然后等待,直到所有请求都得到解决。第一个将一个接一个地发送请求。哪一个更好取决于用例,第二个可能导致请求偷窥,并且可能更容易被DDoS滥用。等待/异步是一种方法,使用常规的等待/异步。。。而不是forEach 异步函数getCardDetails{ 让carsDetails=[]; let user=await user.findByIduserId; const carIds=user.carsDetails; 让龋齿的龋齿{ let car=等待car.findbyidcrad 控制台、行车记录仪; carsdeails.pushcar; } 返回res.status200.json{ 数据:carsDetails }; } 或者你用Promise.all和map代替。。。的
这两种解决方案略有不同。带有映射的第二个版本将立即将所有请求发送到DB,然后等待,直到所有请求都得到解决。第一个将一个接一个地发送请求。哪一个更好取决于用例,第二个可能导致请求偷窥,并且可能更容易被DDoS滥用。如果您可以找到很多车,您可能希望在单个请求中执行查询,而无需堆叠多个承诺:
User.findById(userId)
.then(user => {
const carIds = user.carsDetails;
// if carsDetails is not an array of objectIds do this instead :
// const carIds = user.carsDetails.map(id => mongoose.Types.ObjectId(id));
return Car.find({ _id: { $in: carIds });
})
.then(userCars => {
res.status(200).json({ data: userCars })
})
如果您可以找到很多车,您可能希望在单个请求中执行查询,而无需堆叠多个承诺:
User.findById(userId)
.then(user => {
const carIds = user.carsDetails;
// if carsDetails is not an array of objectIds do this instead :
// const carIds = user.carsDetails.map(id => mongoose.Types.ObjectId(id));
return Car.find({ _id: { $in: carIds });
})
.then(userCars => {
res.status(200).json({ data: userCars })
})
尝试使用async/await解决此问题。它将更加可读和清晰
async function getCarDetail() {
let carsDetails = []
try {
const user = await User.findById(userId)
const carIds = user.carsDetails
for (let i = 0; i < carIds.length; i++) {
const carId = carIds[i]
const car = await Car.findById(carId)
carsDetails.push(car)
}
return res.status(200).json({ data: carsDetails })
} catch(error) {
console.log(error)
}
}
尝试使用async/await解决此问题。它将更加可读和清晰
async function getCarDetail() {
let carsDetails = []
try {
const user = await User.findById(userId)
const carIds = user.carsDetails
for (let i = 0; i < carIds.length; i++) {
const carId = carIds[i]
const car = await Car.findById(carId)
carsDetails.push(car)
}
return res.status(200).json({ data: carsDetails })
} catch(error) {
console.log(error)
}
}
我也尝试过用async await格式编写所有东西,使用自制的async forEach语句,您应该展示您在那里尝试过的内容,因为await/async是一种方式,使用refular的await/async。。。如果它不能正常工作,那么你可能没有正确地使用它。我也尝试过用async Wait的形式编写所有东西,使用自制的async forEach语句,你应该展示你在那里尝试过的东西,因为Wait/async是一种方式,而使用refular的Wait/async。。。of循环而不是forEach.Promise.all,如果它不起作用,那么您可能没有正确使用它。请解释为什么第二种方法是better@AvcS它不一定更好,它是不同的。第二种方法将立即向数据库发送所有请求。请解释为什么第二种方法是better@AvcS它不一定更好,它是不同的。第二个将立即将所有请求发送到db.Car.find{{u id:{$in:carIds}肯定比使用带有Promise的map要好。all,因为它很可能是由DB作为一个查询处理的。这是所有查询中最理想的解决方案。我认为我使用Promise的方式是错误的,但$in选择器确实做得最好。谢谢!一个.catch处理程序会让它更好。@ambianBeing当然,我只想指出一点指出写入.catcherror=>{throw error;};与不写入任何内容相同。catcherror=>{throw error;};毫无用处,因为它除了重试错误之外什么都不做。最好是写入。thenuserCars=>{res.status200.json{data:userCars}.catchnext假设它是express和midde的第三个agrument
使用lware@ambianBeingCar.find{u id:{$in:carIds}肯定比使用带有Promise的map要好。all,因为它很可能是由DB作为一个查询处理的。这是所有查询中最理想的解决方案。我认为我使用Promise的方式是错误的,但$in选择器确实做得最好。谢谢!一个.catch处理程序会让它更好。@ambianBeing当然,我只想指出一点指出写入.catcherror=>{throw error;};与不写入任何内容相同。catcherror=>{throw error;};毫无用处,因为它除了重试错误之外什么都不做。最好是写入。thenuserCars=>{res.status200.json{data:userCars}.catchnext假设它是express,并且使用了中间件的第三个agrument next。@ambianBeingI对可读和干净没有相同的定义,嵌套try/catch块对meI来说非常糟糕没有相同的可读和干净定义,嵌套try/catch块对我来说非常糟糕