如何解决如何在多个嵌套的 forEach 循环中解析 promise?
对于“航班”组合应用程序,我正在尝试为飞机上的每个座位生成机票(以便航班预填充一些人)。这是一个函数的一部分,该函数还预填充到数据库的航班以设置数据。需要调用数据库来检查航班号和确认号是否是唯一的,而不是预先存在的。在航班的情况下,如果航班号已经存在,则航班将被取消。但是,如果在循环中已经存在确认编号,我会遇到一些异步方面的问题,即重新生成确认编号。所以基本上,我遇到的问题:
- generateTickets 返回一个空的票证数组
- 我不确定如何构建嵌套的 forEach 循环,以便在为每一行中的每个座位生成票证时返回 promise。 (在我对 Stack Overflow 的搜索中,我发现了多个引用 Promise.all 和 array.map 的解决方案。我尝试以多种方式实现这些解决方案,但我仍然得到一个空数组,我想我只是不够了解。)
- 我得到:
SyntaxError: Unexpected reserved word
上的await generateConfirmationNumber()
- 即使 generateConfirmationNumber 是一个异步函数
对于我的尝试,我不知道该说什么。这是很多。我搜索了 Google 前 2-3 页的每个链接,我搜索了 Stack Overflow 试图找到解决方案,然后尝试实施它们。我想我只是很难解释他们的代码是如何工作的,因为这有额外的复杂性。我目前在浏览器选项卡上的解决方案是:
- Why doesn't the code after await run right away? Isn't it supposed to be non-blocking?
- Pushing Elements into an Array That Is Inside a Callback Function
- How to wait a Promise inside a forEach loop
- Why does my async function return an empty array
- Best way to wait for .forEach() to complete
- Using async/await with a forEach loop
- How to return values from async functions using async-await from function?
我一直在谷歌上搜索并试图让它工作 3 天,我认为是时候提出一个问题了。 :P 所以到代码! (如果您看到疯狂的全部大写评论,它只会帮助我在控制台中轻松注意到它们。)
createFlight
- 由路由器调用,启动一切。
async function createFlight(req,res) {
create_flights().then(() => {
console.log('Done')
res.redirect('/')
})
}
const create_flights = async() => {
let flights_array = []
let flights_with_tickets = []
for(let i = 0; i < 1; i++) {
let airline = randomAirline();
let origin = randomAirport();
let destination = randomDestination(origin.code);
let duration = generateDuration()
let departure = generateDeparture()
let departure_date = dateString(departure)
let flight_data = {
number: generateFlightNumber(airline.code),airline: airline.name,plane: {
name: randomPlane()
},origin: origin,destination: destination,departure: departure,departure_date: departure_date,duration: duration,gate: generateGate(),amenities: randomAmenities(duration),tickets: []
}
const flight = new Flight(flight_data);
flights_array.push(flight)
}
console.log("FLIGHTS ARRAY")
console.log(flights_array)
for(let flight of flights_array) {
console.log(flight)
const flight_with_ticket = await returnTicketsAsync(flight)
console.log(flight_with_ticket)
if(flight_with_ticket) {
const record = await returnFlight(flight_with_ticket)
console.log(record)
if(record) {
console.log("Created Flight")
console.log(record.tickets[0])
}
}
}
}
returnTicketsAsync
- 等待票据生成。这始终是控制台记录空票证值。
async function returnTicketsAsync(flight) {
console.log("ASYNC TICKETS?!?!?!!?")
let tickets = await generateTickets(flight)
console.log(tickets)
}
returnFlight
- 这会检查航班的确认编号是否已经在数据库中。如果是,我们就跳过这次飞行并继续前进。否则,我们将其保存到数据库中。
const returnFlight = flight => {
return new Promise((resolve,reject) => {
Flight.find({$or:[{number: flight.number}]},function(error,records) {
if(records.length) {
console.log("Similar flight already exists")
resolve()
} else {
flight.save(function (error,result) {
if(error) {
console.log("ERROR:" + error)
resolve()
} else {
resolve(result)
console.log("Flight " + result.number + " successfully saved.")
}
})
}
})
})
}
generateTickets(flight)
- 我所有烦恼的根源。 Flight 有一张平面图,有部分(头等舱、首选舱、经济舱)。每个部分都有带座位的排。
所以我需要遍历头等舱、首选舱和经济舱,生成所有座位的票。有一个函数 generateConfirmationNumber()
生成数字并检查数据库以获取结果。如果没有结果,确认号就可以用了,它会返回那个。我需要等待完成,但我在这里收到 SyntaxError。
async function generateTickets(flight) {
let tickets = []
let prices = generatePrice()
const first_class = await Promise.all(_.map(flight.plane.sections.first_class.rows,async function (row,i,rows) {
let first_class_tickets = await _.map(row,function(seat) {
if(!seat.isle) {
let passenger = generatePassenger()
let confirmation_number = await generateConfirmationNumber()
let tickets = {
confirmation_number: '',tracking_number: generateTrackingNumber(),data: generateDatanumber(),options: '1ST CL',flight_class: 'first',seat: {
isle: seat.letter,number: i + 1
},boarding_zone: generateBoardingzone(),price: prices.first,passenger: passenger
}
if(passenger.first_name !== '' || passenger.first_name.length > 1) {
ticket.confirmation_number = confirmation_number
}
console.log(ticket)
tickets.push(ticket)
}
})
}))
const preferred_class = await Promise.all(_.map(flight.plane.sections.preferred_class.rows,rows) {
let preferred_class_tickets = await _.map(row,options: 'PREF PLUS',flight_class: 'preferred',number: i + flight.plane.sections.first_class.total_rows + 1
},price: prices.preferred,passenger: passenger
}
if(passenger.first_name !== '' || passenger.first_name.length > 1) {
ticket.confirmation_number = confirmation_number
}
console.log(ticket)
tickets.push(ticket)
}
})
}))
const economy_class = await Promise.all(_.map(flight.plane.sections.economy_class.rows,rows) {
let economy_class_tickets = await _.map(row,number: i + flight.plane.sections.first_class.total_rows + flight.plane.sections.preferred_class.total_rows + 1
},price: prices.economy,passenger: passenger
}
if(passenger.first_name !== '' || passenger.first_name.length > 1) {
ticket.confirmation_number = confirmation_number
}
console.log(ticket)
tickets.push(ticket)
}
})
}))
console.log("Tickets")
console.log(ticekts)
}
generateConfirmationNumber
- 也把这个扔在这里。
async function generateConfirmationNumber() {
let letters = 'ABCDEFGHJKLMNPRSTUVWXYZ'
let number = Math.floor(Math.random() * 10000)
let confirmation = letters[Math.floor(Math.random() * letters.length)] + letters[Math.floor(Math.random() * letters.length)] + letters[Math.floor(Math.random() * letters.length)] + number
return new Promise((resolve,reject) => {
Flight.findOne({'tickets.confirmation_number': confirmation},(err,result) => {
if (err) console.log(error)
else if (result) return resolve(generateConfirmationNumber())
else return resolve(confirmation)
})
})
}
我不知道如何让它工作。目标只是生成机票,等待 generateConfirmationNumber()
完成,然后将所有机票推送到该航班的“tickets”数组中。然后,返回该数组,以便它可以 $set 到航班,然后,航班可以被推送到数据库中。
解决方法
您的代码不起作用的主要问题是,您尝试将 Promise.all() 转换为下面的 ticket
数组。
Promise.all 仅适用于 promises 对象,但您可以看到 ticket
本身并不是一个纯粹的 Promise 对象。此外, map() 函数不会等待循环中的承诺。如果您想在循环中等待承诺,则需要使用 for loop
。
let confirmation_number = await generateConfirmationNumber();
let ticket = {
confirmation_number: confirmation_number,tracking_number: generateTrackingNumber(),data: generateDataNumber(),options: "1ST CL",flight_class: "first",seat: {
isle: seat.letter,number: i + 1,},boarding_zone: generateBoardingZone(),price: prices.first,passenger: generatePassenger(),};
以下代码不起作用,因为票证不是承诺对象。
Promise.all([ticket1,ticket2,ticket3]);
要使其发挥作用,您有两个选择。
-
Promises in Parallel:Promise.all 所有的 promises 对象并使用
array#map()
创建一个票证对象数组。 -
Promises in Series:等待每一个 Promise 并一一构造票证。
如果您想以并行方式执行 Promises,您可以执行以下操作:
const arrayOfPromises = flight.plane.sections.first_class.rows.flatMap(row =>
row.map(seat => generateConfirmationNumber())
);
const confirmationNumbers = await Promise.all(arrayOfPromises);
const tickets = confirmationNumbers.map(cfmNumber => ({
confirmation_number: cfmNumber,}));
我使用的答案是第二个选项(Promises in Series)。
我使用 for of 循环来等待每个承诺并从中创建一个票证。 最后,我将票添加到一个票证数组中。
async function generateTickets(flight) {
let tickets = [];
let prices = generatePrice();
const firstClass = [];
for (const row of flight.plane.sections.first_class.rows) {
for (const seat of row) {
if (!seat.isle) {
const passenger = generatePassenger();
const confirmation_number = await generateConfirmationNumber();
const ticket = {
confirmation_number: "",seat: {
isle: seat.letter,number: flight.plane.sections.first_class.rows.indexOf(row) + 1,passenger: passenger,};
if (passenger.first_name !== "" || passenger.first_name.length > 1) {
ticket.confirmation_number = confirmation_number;
}
firstClass.push(ticket);
}
}
}
console.log(firstClass);
const preferredClassTickets = [];
for (const row of flight.plane.sections.preferred_class.rows) {
for (const seat of row) {
if (!seat.isle) {
let passenger = generatePassenger();
let confirmation_number = await generateConfirmationNumber();
let ticket = {
confirmation_number: "",options: "PREF PLUS",flight_class: "preferred",number: flight.plane.sections.preferred_class.rows.indexOf(row) + flight.plane.sections.first_class.total_rows + 1,price: prices.preferred,};
if (passenger.first_name !== "" || passenger.first_name.length > 1) {
ticket.confirmation_number = confirmation_number;
}
preferredClassTickets.push(ticket);
}
}
}
const economyClass = [];
for (const row of flight.plane.sections.economy_class.rows) {
for (const seat of row) {
if (!seat.isle) {
let passenger = generatePassenger();
let confirmation_number = await generateConfirmationNumber();
let ticket = {
confirmation_number: "",number:
flight.plane.sections.economy_class.rows.indexOf(row) +
flight.plane.sections.first_class.total_rows +
flight.plane.sections.preferred_class.total_rows +
1,price: prices.economy,};
if (passenger.first_name !== "" || passenger.first_name.length > 1) {
ticket.confirmation_number = confirmation_number;
}
economyClass.push(ticket);
}
}
}
tickets.push(...firstClass,...preferredClassTickets,...economyClass);
return tickets;
}
async function generateConfirmationNumber() {
let letters = "ABCDEFGHJKLMNPRSTUVWXYZ";
let number = Math.floor(Math.random() * 10000);
let confirmation =
letters[Math.floor(Math.random() * letters.length)] +
letters[Math.floor(Math.random() * letters.length)] +
letters[Math.floor(Math.random() * letters.length)] +
number;
return new Promise((resolve,reject) => {
Flight.findOne(
{ "tickets.confirmation_number": confirmation },(err,result) => {
if (err) reject(error);
// else if (result) return resolve(generateConfirmationNumber());
else if (result) return resolve(result);
else return resolve(confirmation);
}
);
});
}
const returnFlight = flight => {
return new Promise((resolve,reject) => {
Flight.find(
{ $or: [{ number: flight.number }] },function (error,records) {
if (error) reject(error);
if (records.length) {
console.log("Similar flight already exists");
resolve(records);
} else {
flight.save(function (error,result) {
if (error) {
console.log("ERROR:" + error);
reject(error);
} else {
console.log("Flight " + result.number + " successfully saved.");
resolve(result);
}
});
}
}
);
});
};
const create_flights = async () => {
let flights_array = [];
// let flights_with_tickets = [];
for (let i = 0; i < 1; i++) {
let airline = randomAirline();
let origin = randomAirport();
let destination = randomDestination(origin.code);
let duration = generateDuration();
let departure = generateDeparture();
let departure_date = dateString(departure);
let flight_data = {
number: generateFlightNumber(airline.code),airline: airline.name,plane: {
name: randomPlane(),origin: origin,destination: destination,departure: departure,departure_date: departure_date,duration: duration,gate: generateGate(),amenities: randomAmenities(duration),tickets: [],};
const flight = new Flight(flight_data);
flights_array.push(flight);
}
console.log("FLIGHTS ARRAY");
console.log(flights_array);
for (let flight of flights_array) {
const tickets = await generateTickets(flight);
if (tickets) {
flight.set({
tickets: tickets
})
const record = await returnFlight(flight);
console.log(record);
if (record) {
console.log("Created Flight");
console.log(record.tickets);
}
}
}
};
async function createFlight(req,res) {
try {
await create_flights();
console.log("Done");
res.redirect("/");
} catch (err) {
console.log(err);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。