微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在多个嵌套的 forEach 循环中解析 promise?

如何解决如何在多个嵌套的 forEach 循环中解析 promise?

对于“航班”组合应用程序,我正在尝试为飞机上的每个座位生成机票(以便航班预填充一些人)。这是一个函数的一部分,该函数还预填充到数据库的航班以设置数据。需要调用数据库来检查航班号和确认号是否是唯一的,而不是预先存在的。在航班的情况下,如果航班号已经存在,则航班将被取消。但是,如果在循环中已经存在确认编号,我会遇到一些异步方面的问题,即重新生成确认编号。所以基本上,我遇到的问题:

  1. generateTickets 返回一个空的票证数组
  2. 我不确定如何构建嵌套的 forEach 循环,以便在为每一行中的每个座位生成票证时返回 promise。 (在我对 Stack Overflow 的搜索中,我发现了多个引用 Promise.all 和 array.map 的解决方案。我尝试以多种方式实现这些解决方案,但我仍然得到一个空数组,我想我只是不够了解。)
  3. 我得到:SyntaxError: Unexpected reserved word 上的 await generateConfirmationNumber() - 即使 generateConfirmationNumber 是一个异步函数

对于我的尝试,我不知道该说什么。这是很多。我搜索了 Google 前 2-3 页的每个链接,我搜索了 Stack Overflow 试图找到解决方案,然后尝试实施它们。我想我只是很难解释他们的代码是如何工作的,因为这有额外的复杂性。我目前在浏览器选项卡上的解决方案是:

我一直在谷歌上搜索并试图让它工作 3 天,我认为是时候提出一个问题了。 :P 所以到代码! (如果您看到疯狂的全部大写评论,它只会帮助我在控制台中轻松注意到它们。)

createFlight - 由路由器调用,启动一切。

async function createFlight(req,res) {
    create_flights().then(() => {
        console.log('Done')
        res.redirect('/')
    })
}

create_flights - 生成随机飞行的异步函数

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]);

要使其发挥作用,您有两个选择。

  1. Promises in Parallel:Promise.all 所有的 promises 对象并使用 array#map() 创建一个票证对象数组。

  2. 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 举报,一经查实,本站将立刻删除。