Как дождаться цикла асинхронных операций?

У меня есть конечная точка исправления, которая обновляет тело полей, выполняет итерацию по каждому полю и обновляет правильное значение. Я хочу что-то сделать, отправить ответ, как только все это будет сделано, но я не знаю, как дождаться цикла операций. Если бы это была единственная операция, я мог бы просто добавить .then(), но в данном случае это не сработало бы. Какое элегантное решение для этого?

Код:

const updateUser = (req, res) => {
    const db = mongoConnection.getDb();
    for (key in req.body) {
        db.collection('users').updateOne(
            {username: req.query.username},
            {$set: {[key]: req.body[key]}}
        )
    }
    // send response once for loop is done
}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
33
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я думаю, что простым ответом было бы скрыть цикл for в асинхронной функции, а затем использовать его в конечной точке.

const updateUserField = async () =>
  db.collection("users").updateOne(
    {
      username: req.query.username,
    },
    {
      $set: { [key]: req.body[key] },
    }
  );


const updateUserEndpoint = (req, res) => {
   for (let field of req.body) {
      await updateUserField(field);
   }

   res.status(200).send('updated');
}

Затем для тестирования вы можете обернуть конечную точку функцией, которая внедряет саму функцию:

const updateUserEndpoint = (userUpdateFunc) => userUpdateFunc(req, res);

Этот паттерн называется внедрением зависимостей — при написании модульных тестов для конечной точки вы просто замените userUpdateFunc любой фиктивной функцией, которую хотите использовать. Это избавляет от необходимости исправлять функцию в тесте.

Функция updateUserField() избыточна, так как updateOne() уже возвращает обещание. Также updateUserField - это () => {}, который не принимает аргументов, но вы называете его updateUserField(field), он должен быть либо updateUserField() (удалить field), либо updateUserField = (field) => {}

slebetman 23.03.2022 03:13

Вы забыли отметить updateUserEndpoint как async. Также внутри updateUserField вы не возвращаете обновление БД, так что на самом деле ждать нечего. Функция также не использует аргумент поля. Это решение, как оно есть, не работает. Лучшее решение — запускать обновления параллельно, как указано в моем ответе ниже.

Maxim Orlov 24.03.2022 17:53

Вы можете пометить внешнюю функцию async и await каждое обновление БД внутри цикла. Тогда вы узнаете, что после завершения цикла все обновления БД выполняются.

Еще лучше запускать обновления параллельно, так как они не зависят друг от друга. Вы можете использовать Promise.allSettled(), который принимает массив обещаний и разрешается, когда завершается последнее.

const updateUser = async (req, res) => {
  const db = mongoConnection.getDb();
  
  const dbUpdates = Object.entries(req.body).map((key, value) => {
    return db.collection('users').updateOne(
      { username: req.query.username },
      { $set: { [key]: value }}
    );
  });

  await Promise.allSettled(dbUpdates);

  // Send response, at this point all DB updates are done
};

Другие вопросы по теме