我对目标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"
]
}
答案 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')
}
}
希望我根据您提供的代码与您尝试完成的内容相匹配。如果这个更新的代码出现问题,请在评论中告诉我。