javascript - 在 TypeScript API 中跳过异步等待
问题描述
我在设置结果对象的控制器中有一个异步方法。问题不是等待await
完成执行我的代码而是跳转到响应对象调用,这使得所需的变量未定义。在调试器中,应该执行的方法中的断点在未定义的错误之后被命中。谁能解释为什么异步等待在这里不起作用?
控制器类中的方法:
public async loginUser(req: Request, res: Response) {
const { name, password } = req.body;
let result: ILoginResult = await UserData.login(name, password); // always undefined
res.status(result.status).send(result.result); // gets hit before result is set
}
用户数据类:
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import mongoose from 'mongoose';
import ILoginResult from './ILoginResult';
import UserModel from '../../models/UserModel';
class UserData {
private connUri: string;
constructor() {
this.connUri = process.env.MONGO_LOCAL_CONN_URL;
}
public async login(name: string, password: string) {
try {
await mongoose.connect(this.connUri, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, }, (err) => {
let result: ILoginResult = { status: 0, result: null, error: '', token: '' };
let status = 200;
if (!err) {
UserModel.findOne({ name }, (err, user) => {
if (!err && user) {
// We could compare passwords in our model instead of below as well
bcrypt.compare(password, user.password).then(match => {
if (match) {
status = 200;
// Create a token
const payload = { user: user.name };
const options = { expiresIn: '2d', issuer: 'http://localhost' };
const secret = process.env.JWT_SECRET;
const token = jwt.sign(payload, secret, options);
// console.log('TOKEN', token);
result.token = token;
result.status = status;
result.result = user;
} else {
status = 401;
result.status = status;
result.error = `Authentication error`;
}
return result;
}).catch(err => {
status = 500;
result.status = status;
result.error = err;
return { status: status, result: result };
});
} else {
status = 404;
result.status = status;
result.error = err;
return result;
}
});
} else {
status = 500;
result.status = status;
result.error = err.toString();
return result;
}
});
} catch (e) {
let result: ILoginResult;
result.error = e.toString();
result.status = 500;
return result;
}
}
}
export default new UserData();
解决方案
不要将async
/await
直接与基于回调的 API 混合使用。
根据文档,mongoose.connect
确实返回了一个承诺(前提是您使用的是最新版本),但没有任何迹象表明它会让该承诺等待您给它的回调中发生的事情。
相反,在await mongoose.connect
.
沿着这些思路(在UserData
):
public async login(name: string, password: string) {
let result: ILoginResult = { status: 0, result: null, error: '', token: '' };
try {
await mongoose.connect(this.connUri, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, });
const user = await UserModel.findOne({ name });
let status = 200;
let match = await bcrypt.compare(password, user.password).catch(() => false);
if (!match) {
status = 401;
result.status = status;
result.error = `Authentication error`;
return result;
}
status = 200;
// Create a token
const payload = { user: user.name };
const options = { expiresIn: '2d', issuer: 'http://localhost' };
const secret = process.env.JWT_SECRET;
const token = jwt.sign(payload, secret, options);
// console.log('TOKEN', token);
result.token = token;
result.status = status;
result.result = user;
return result;
} catch (e) {
result.error = e.toString();
result.status = 500;
return result;
}
}
推荐阅读
- python - H2O Word2Vec 不一致向量
- typescript - 标记联合类型上的 Visual Studio 代码错误
- php - 帖子列表未显示在 Wordpress 管理面板中
- lambda - Java8 stream.map 在同一个流上输出不同的映射函数?
- r - 使用 Microsoft R 在 RStudio 中加载 CPP 文件时出错
- node.js - 猫鼬找到一个并更新功能
- jquery - jQuery Ajax 表单在出错时获取提交的表单作为返回参数
- entity-framework - Entity Framework 6 Code First 迁移不适用于 Oracle 数据库
- java - JBoss AS 7.1.1 和动态过滤器实例注册
- android - 无法解决导入 com.google.android.gms