Правильное использование async/await с функциями обратного вызова

Я пытаюсь создать сервисный слой поверх монго. У меня есть объект User, который имеет массив ссылок Achievements.

После того, как я аутентифицировал пользователя с помощью JWT или каким-либо другим способом, я вхожу на уровень службы и запрашиваю отношение следующим образом.

findForUser(userId: string | Types.ObjectId): Promise<Achievement[]> {
  return new Promise((resolve) => {
    UserSchema.findOne({ _id: userId },
      async (err: any, user: User) => {
        const AchievementMap: Achievement[] = [];

        if (err) throw new Error(err);
        user.achievements?.forEach((a) => {
          // @ts-ignore
          AchievementMap.push(a);
        });
        resolve(AchievementMap);
      });
  });
}

Мой вопрос действительно таков: каков подход async/await к возврату результата метода обратного вызова, переданного в UserSchema.findOne?


person Ross Burchnall    schedule 30.01.2021    source источник


Ответы (2)


findOne возвращает ожидаемый объект, поэтому вам не нужно передавать ему обратный вызов. Не пытайтесь смешивать обратные вызовы с async/await. Единственный способ вернуть значение из обратного вызова в результате сконструированного промиса — использовать resolve (доступно только в исполнителе промиса).

Вместо этого сделайте все async — функционально похожим, но намного чище.

async findForUser(userId: string | Types.ObjectId): Promise<Achievement[]> {
    const user = await UserSchema.findOne({ _id: userId });

    const AchievementMap: Achievement[] = [];
    user.achievements?.forEach(a => {
        AchievementMap.push(a);
    });
    return AchievementMap;
}
person Chase    schedule 30.01.2021

Что такое асинхронный/ожидающий подход к возврату результата обратного вызова

Ключевые слова async и await — это инструменты для управления обещаниями. Они не являются инструментами для управления обратными вызовами.

Весь смысл кода, который у вас есть в вопросе, состоит в том, чтобы обернуть API на основе обещаний вокруг функции, которая имеет дело с обратными вызовами.

Теперь у вас есть обещание, что вы можете await возвращать значение findForUser.

Вы не можете использовать async и await вместо создания промиса.

person Quentin    schedule 30.01.2021