打字稿async /等待不起作用

时间:2017-09-27 09:50:42

标签: node.js typescript asynchronous async-await sequelize.js

我对目标es2017的打字稿上的async / await问题。以下是我的代码:

my route.ts:

method: 'POST',
        config: {            
            auth: {
                strategy: 'token',        
            }
        },
        path: '/users',
        handler: (request, reply) {

    let { username, password } = request.payload;

    const getOperation = User
    .findAll({
        where: {
            username: username
        }
    })
    .then(([User]) => {
        if(!User) {
            reply({
                error: true,
                errMessage: 'The specified user was not found'
            });
            return;
        }

        let comparedPassword = compareHashPassword(User.password, password);
        console.log(comparedPassword);

        if(comparedPassword) {
            const token = jwt.sign({
                username,
                scope: User.id

            }, 'iJiYpmaVwXMp8PpzPkWqc9ShQ5UhyEfy', {
                algorithm: 'HS256',
                expiresIn: '1h'
            });

            reply({
                token,
                scope: User.id
            });
        } else {
            reply('incorrect password');
        }
    } )
    .catch(error => { reply('server-side error') });

};

my helper.ts:

export async function compareHashPassword(pw:string, originalPw:string) {
    console.log(pw);
    console.log(originalPw);
    let compared = bcrypt.compare(originalPw, pw, function(err, isMatch) {
        if(err) {
                return console.error(err);
        }
        console.log(isMatch);
        return isMatch;
        });

    return await compared;
}

此auth路由应该在用户登录时返回JWT令牌。但这里的问题是,即使我输入有效密码登录函数,compareHashPassword也总是返回undefined。

例如,当我用json字符串

调用api时
{
  "username": "x",
  "password": "helloword"
}

当我使用console.log()进行跟踪时,日志为:

$2a$10$Y9wkjblablabla -> hashed password stored in db
helloword 
Promise {
  <pending>,
  domain: 
   Domain {
     domain: null,
     _events: { error: [Function: bound ] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] } }
true

也许这只是我对使用ascript / await和typescript缺乏了解。注意我的环境是:

node : v8.6.0
typescript : v2.5.2
ts-node : v3.3.0
my tsconfig.json //
{
    "compilerOptions": {
        "outDir": "dist",
        "target": "es2017",
        "module": "commonjs",
        "removeComments": true,
        "types": [
            "node"
        ],
        "allowJs": true,
        "moduleResolution": "classic"
    },
    "exclude": [
        "node_modules"
    ]
}

2 个答案:

答案 0 :(得分:6)

为了使async / await工作,异步函数必须返回Promise。此外,您必须使用await关键字以这种方式调用async

您只能在异步函数内调用await,因此我将其包装在异步函数中

const someFunc = async function() {
    return new Promise((resolve, reject) => { 
        setTimeout(resolve, 100, true);
    });
};

(async () => {
     const result = await someFunc(); // true
})();

您在compareHashPassword声明中以及您调用它的方式不满足任何这些规则。

这是我重写代码的方式:

export async function compareHashPassword(pw:string, originalPw:string) {
    return new Promise((resolve, reject) => {
        bcrypt.compare(originalPw, pw, function(err, isMatch) {
            if(err) {
                reject(err);
            }
            console.log(isMatch);
            resolve(isMatch);
        });
    });
}

// and call it this way
(async () => {
     const compared = await compareHashPassword(pw, originPw);
})()

看看这个异步等待博客文章: https://ponyfoo.com/articles/understanding-javascript-async-await

这篇关于Promises的博文: https://developers.google.com/web/fundamentals/primers/promises

同样@Patrick Roberts提到,您可以使用util.promisify将异步回调样式函数转换为Promise,这是node 8.xx,否则您可以使用具有类似功能的bluebird包功能。

希望这有帮助

答案 1 :(得分:4)

由于您的目标是ES2017,让我们清理您的代码,从更简单的helper.ts开始:

import { promisify } from 'util' // you'll thank me later

const compare = promisify(bcrypt.compare)

export async function compareHashPassword(pw:string, originalPw:string) {
    console.log(pw);
    console.log(originalPw);
    return compare(originalPw, pw);
}

现在为route.ts

handler: async (request, reply) => {
  let { username, password } = request.payload;

  try {
    const [user] = await User.findAll({
      where: {
        username: username
      }
    })

    if(!user) {
      reply({
        error: true,
        errMessage: 'The specified user was not found'
      });

      return;
    }

    let match = await compareHashPassword(user.password, password);

    console.log(match);

    if (match) {
      const token = jwt.sign({
        username,
        scope: User.id
      }, 'iJiYpmaVwXMp8PpzPkWqc9ShQ5UhyEfy', {
        algorithm: 'HS256',
        expiresIn: '1h'
      });

      reply({
        token,
        scope: user.id
      });
    } else {
      reply('incorrect password');
    }
  } catch (error) {
    reply('server-side error')
  }
}

希望我根据您提供的代码与您尝试完成的内容相匹配。如果这个更新的代码出现问题,请在评论中告诉我。