Как реализовать асинхронный цикл (JS)

1

У меня есть для каждого цикла, где я проверяю что-то внутри него. Эта проверка является асинхронной, и когда эта проверка ложна, я хочу разбить цикл. Вот мой код:

addReservation(reservation: Reservation) {
    this.deskService.loadDesksWhereRangeGreater(reservation.persons).subscribe(
        desks => {
            if (desks.length > 0) {

                for (const desk1 of desks) {
                    console.log('checking');
                    if (this.checkForAvailability(desk1, reservation)) {
                        console.log('found');
                    }
                }
            }
        }
    );
}

async checkForAvailability(desk: Desk, reservation: Reservation) {

    await this.db.collection('Desks').doc(desk.id)
    .collection('Reservations', ref => ref.where('timestamp', '<=', reservation.timestamp + this.reservationDelta)
    .where('timestamp', '>', reservation.timestamp - this.reservationDelta))
    .valueChanges().subscribe(reservations => {
        if (reservations.length === 0) {
            console.log('reservation possible for ' + desk.nr);
            return true;
        } else {
            console.log(desk.nr + ' Belegt');
            return false;
        }
    });
}

Однако часть await не работает. Он просто выполняет цикл через цикл, не дожидаясь асинхронной функции каждой итерации.

  • 0
    Вам нужно вернуть обещание от checkForAvailability и async await в addReservation
  • 0
    Возможный дубликат Как я могу вернуть ответ от асинхронного вызова?
Показать ещё 1 комментарий
Теги:
angular
async-await

2 ответа

1
Лучший ответ

Вам нужно await результата checkForAvailability:

addReservation(reservation: Reservation) {
    this.deskService.loadDesksWhereRangeGreater(reservation.persons).subscribe(
        async desks => {
            if (desks.length > 0) {
                for (const desk of desks) {
                    const available = await this.checkForAvailability(desk, reservation)
                    if (!available) { break }
                }
            }
        }
    );
}

checkForAvailability(desk: Desk, reservation: Reservation) {
  // here, you need to return a promise
  return new Promise(resolve => {
    this.db.collection('Desks').doc(desk.id)
    .collection('Reservations', ref => ref.where('timestamp', '<=', reservation.timestamp + this.reservationDelta)
    .where('timestamp', '>', reservation.timestamp - this.reservationDelta))
    .valueChanges().subscribe(reservations => {
      resolve(reservations.length === 0)
    });
  })
}
  • 0
    Спасибо, я получил идею, но когда я делаю const available = await this.checkForAvailability(desk, reservation); Я получаю синтаксическую ошибку "выражение" ожидание "разрешено только в асинхронной функции". Я объявил функцию addReservation как асинхронную.
  • 0
    Хорошо, вы должны объявить внутренний обратный вызов как асинхронный, обновил мой ответ.
Показать ещё 1 комментарий
1

Вам нужно вернуть Promise в функции checkForAvailability, а функция addReservation должна быть асинхронной, чтобы использовать await.

Оператор ожидания используется для ожидания Promise. Его можно использовать только в асинхронной функции.

Здесь пример того, как реализовать цикл async:

async function asyncLoop(){
  console.log('loop 10 times')
  for(let i=0; i<10; i++) await doSomethingAsync(i);
  console.log('loop done!')
}

function doSomethingAsync(i){
  return new Promise( function(resolve,reject){
    // do your async stuff ... and then resolve()
    //
    // in this example i will use a timeout to simulate
    // an async operation.
    setTimeout( function(){
      console.log(i,'done!');
      resolve();
    }, 1000);
  })
}

asyncLoop()
  • 0
    Спасибо, у меня есть концепция.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню