打字稿异步/等待不起作用
Posted
技术标签:
【中文标题】打字稿异步/等待不起作用【英文标题】:Typescript async/await not working 【发布时间】:2018-03-08 18:10:07 【问题描述】:我对目标 es2017 的打字稿上的 async/await 有疑问。以下是我的代码:
我的 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') );
;
我的 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;
此身份验证路由应该在用户登录时返回 JWT 令牌。但这里的问题是即使我输入有效密码登录函数 compareHashPassword 总是返回未定义。
例如当我用 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
也许这只是我对使用 async/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"
]
【问题讨论】:
【参考方案1】:为了使 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
包。
希望对你有帮助
【讨论】:
目前,您只能在异步函数中调用 await 根据规范,总是就是这样,只是说。 我觉得这很可悲,虽然我没有检查 v8 中的实现本身。感谢您的提示,我会更新我的答案 顺便说一下,在您的第一个示例中,Promise.resolve(...)
是多余的。您所要做的就是return true
和async
函数将隐式强制它成为一个已解决的承诺。
我不知道,所以明确地返回一个 Promise 只需要在回调样式异步调用时完成?
现在你的new Promise()
不再是多余的了,但我个人更喜欢这样写setTimeout(resolve, 100, true);
只是为了思考~【参考方案2】:
由于您的目标是 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')
希望我已经根据您提供的代码匹配了您想要完成的任务。如果此更新后的代码有问题,请在 cmets 中告诉我。
【讨论】:
哇,这对 node.js 来说真的很有帮助。感谢您的所有回答。您的两个解决方案都有效,并帮助我了解异步的工作原理。干杯。以上是关于打字稿异步/等待不起作用的主要内容,如果未能解决你的问题,请参考以下文章