Передайте асинхронный обратный вызов в конструктор класса, используя TypeScript и Node / Passport - PullRequest
0 голосов
/ 08 февраля 2019

Я использую библиотеку аутентификации passport-http, в документации которой используются обратные вызовы, но я использую классы TypeScript с async / await, поэтому не уверен в синтаксисе.

Библиотека хочет обратный вызов verify, который запрашивает базу данных, что является асинхронной операцией.Я определил ее как отдельную асинхронную функцию (чтобы ее было проще проверить):

public verify = async (username: string, password: string, done: (error: any, user?: any) => void): Promise<void> => {
  // read from database asynchronously...
  try {
    const user = await this.UserRepository.findByUsername(username);
    if (!user)
      return done(null, false);
    if (user.Password !== password)
      return done(null, false);
    return done(null, user);
  }
  catch (e) {
    return done(e);
  }
}

Затем я предоставляю ее библиотеке:

//public async init(): Promise<void> {                       // also works
public init(): void {
  const strategy = new PassportBasicStrategy(this.verify);   // async callback!
  passport.use(strategy);
}

Мои проблемы:

  • Если я объявлю это как init() вместо async init(), это будет работать.Я предполагаю, что это потому, что модификатор async необходим только в том случае, если функция имеет await?
  • Но я передал асинхронный обратный вызов в этот конструктор, в функции синхронизации! ... Это правильно?

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Если вы хотите воспользоваться API async / await.В этом случае, поскольку API основан на обратном вызове, вы можете сделать следующее:

const veryfy: BasicVerifyFunction = (username, password, done) => {
    (async () => {
        try {
            const user = await User.findOne({
                username: username,
                password: password
            });
            done(null, user ? user : false);
        } catch(err) {
            done(err);
        }
    })();
};

passport.use(new BasicStrategy(veryfy));

Обратите внимание на async IIFE :

(async () => {
    // Use await here
})();

Node.js такжевключает вспомогательную функцию с именем promisify для преобразования API обратного вызова в API Promise, но в этом случае ее нельзя использовать.

0 голосов
/ 08 февраля 2019

async - синтаксический сахар для обычной функции, которая возвращает обещание.Если функция не использует await, ей не выгодно быть async.

Если API, принимающий обратный вызов, не использует обещание, которое она возвращает, это потенциальная проблема.Допустимо использовать обещания и, следовательно, async, если эта проблема решена.Поскольку API не будет обрабатывать отклонения, они должны обрабатываться пользователем:

verify = async (username: string, password: string, done: (error: any, user?: any) => void): Promise<void> => {
  try {
    // reads from the database asynchronously...
    done(null, user);
  } catch (err) {
    done(err);
  }
}

Не вызывая done обратный вызов приведет к некорректному поведению, даже если возвращенное обещание выполнено.

Но я передал асинхронный обратный вызов в этот конструктор, в функции синхронизации

PassportBasicStrategy принимает потенциально асинхронные обратные вызовы, поэтому обратные вызовы имеют параметр done.Не имеет значения, является ли функция async или нет, если возвращаемое обещание ни на что не влияет.

...