当前位置: 首页 > 知识库问答 >
问题:

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

衡泰
2023-03-14

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

  1. Generateckets返回一个空票证数组

我不知道该怎么说我的努力。这是很多。我搜索了Google前2-3页的每个链接,我搜索了堆栈溢出,试图找到解决方案,然后尝试实现它们。我想我只是很难解释他们的代码是如何工作的,而这又增加了复杂性。我当前在浏览器选项卡上的解决方案有:

  • 为什么等待后的代码不能立即运行?它不应该是非阻塞的吗
  • 将元素推入回调函数内的数组
  • 如何在forEach循环中等待promise
  • 为什么我的异步函数返回空数组
  • 等待的最佳方式。forEach()完成
  • 将异步/等待与forEach循环一起使用
  • 如何使用async Wait from函数从异步函数返回值

我已经用谷歌搜索并试图让它工作了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])
            }
        }
        
    }
}

returTicketsAsync-等待生成票证。这始终是控制台记录空票证值。

async function returnTicketsAsync(flight) {
    console.log("ASYNC TICKETS?!?!?!!?")
    let tickets = await generateTickets(flight)
    console.log(tickets)
}

返回航班-检查航班的确认号是否已经在数据库中。如果是,我们就跳过这趟航班,继续前进。否则,我们将其保存到数据库中。

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(航班)-我所有麻烦的根源。该航班有一张飞机地图,上面有部分(头等舱、头等舱、经济舱)。每个部分都有带座位的行。所以我需要遍历头等舱、头等舱和经济舱,生成所有座位的票。有一个函数,即generateConfirmationNumber(),用于生成数字,并检查数据库中的结果。如果没有结果,则可以使用确认号,并返回该编号。我需要等待,但我这里有一个语法错误。

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, async function (row, i, rows) {
        let preferred_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: 'PREF PLUS',
                    flight_class: 'preferred',
                    seat: {
                        isle: seat.letter,
                        number: i + flight.plane.sections.first_class.total_rows + 1
                    },
                    boarding_zone: generateBoardingZone(),
                    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, async function (row, i, rows) {
        let economy_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: 'PREF PLUS',
                    flight_class: 'preferred',
                    seat: {
                        isle: seat.letter,
                        number: i + flight.plane.sections.first_class.total_rows + flight.plane.sections.preferred_class.total_rows + 1
                    },
                    boarding_zone: generateBoardingZone(),
                    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()完成,然后将所有机票推送到该航班的“机票”数组中。然后,返回该数组,以便将其设置为航班的$,然后,航班可以推送到数据库中。

共有1个答案

庞修贤
2023-03-14

您的代码无法工作的主要问题是因为您尝试将Promise.all()到下面的票证的数组。Promise.all只处理Promise对象,但您可以看到票证本身不是一个纯粹的Promise对象。此外,map()函数不会在循环中等待Promise。如果您想在循环中等待Promise,则需要使用for循环

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对象。

Promise.all([ticket1,ticket2,ticket3]);

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

>

系列promise:等待每一个promise,并逐一构建门票。

如果你想以平行的方式做出promise,你可以像下面这样做:

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,
  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)。

我使用for of循环来等待每个promise并从中创建一个票证。最后,我将票证添加到数组票证中。

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: "",
            tracking_number: generateTrackingNumber(),
            data: generateDataNumber(),
            options: "1ST CL",
            flight_class: "first",
            seat: {
              isle: seat.letter,
              number: flight.plane.sections.first_class.rows.indexOf(row) + 1,
            },
            boarding_zone: generateBoardingZone(),
            price: prices.first,
            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: "",
            tracking_number: generateTrackingNumber(),
            data: generateDataNumber(),
            options: "PREF PLUS",
            flight_class: "preferred",
            seat: {
              isle: seat.letter,
              number: flight.plane.sections.preferred_class.rows.indexOf(row) + flight.plane.sections.first_class.total_rows + 1,
            },
            boarding_zone: generateBoardingZone(),
            price: prices.preferred,
            passenger: passenger,
          };
  
          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: "",
            tracking_number: generateTrackingNumber(),
            data: generateDataNumber(),
            options: "PREF PLUS",
            flight_class: "preferred",
            seat: {
              isle: seat.letter,
              number:
                flight.plane.sections.economy_class.rows.indexOf(row) +
                flight.plane.sections.first_class.total_rows +
                flight.plane.sections.preferred_class.total_rows +
                1,
            },
            boarding_zone: generateBoardingZone(),
            price: prices.economy,
            passenger: passenger,
          };
  
          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);
    }
  }
 类似资料:
  • 这是我的代码。我遇到的问题是,我希望将HP在我的PHP代码中的数字转换为我的HP HTML代码,以及与Cylinder相同的内容。我已经想好了其他的东西,但说到这一部分我就卡住了

  • 我有一个这样的数组 我想做的是前面的模型,为其数量绘制徽标,因此三星=3,索尼=7,以此类推,将绘制3个索尼徽标和7个三星徽标。 我想出了这样的办法 但是当然,所有这些都是为了每个数组条目,呼应出名称,所以我最终打印了5个三星,打印了5个索尼,等等。 如何使其使用 qty 数组的值而不是条目数?

  • 我的代码有一个问题,它有两个嵌套的foreach循环: 所以我在“消息”中有2个条目,在“评论”中有4个条目,第一个条目为“消息”,第二个条目为2。我想要: 消息1-评论1-评论2 消息2-注释3-注释4 这就是我所拥有的: 消息1-评论1-评论2 消息2-注释1-注释2-注释3-注释4 我搜索了两个小时,在mysqli中没有找到解决方案:((当我找到时 mysqli_data_seek($com

  • 我正在寻找一种用函数式编程方法替换嵌套foreach循环的方法。情况是这样的: 目前我的代码是这样的: 这将生成如下所示的输出: 有谁知道如何用函数式编程替代方案替换foreach代码块?

  • 问题内容: 我有四个foreach循环,这些循环遍历集合并根据条件进行操作。 这是我现在正在编写的代码: 主要对象(代码中的对象)来自第三方提供程序SDK,因此我无法在该部分上进行任何更改。我想问一下Stack Overflow社区是否有更好的方法来打破所有四个foreach循环。或者,如果还有其他方法可以重构此代码,使其更具可读性和可维护性。 问题答案: 在最外面的循环上使用标签,当您想跳出所有

  • 数据库表: 胶片(id\U胶片主键,名称) 流派(id_genrePK,名称) film_genre(id_filmFK,id_genreFK) 这将输出流派表中的所有流派: 这将输出特定电影的电影类型表中的所有选定类型: 我有一个问题,从数据库输出数据到多个选定的列表中的形式。这是一个电影数据库,我正在进行Foreach迭代,以读取电影流派的所有行,并输出到多个选择字段。但是我在向列表输出“选定