使用await时出现无限等待,Refresh Token异步函数无返回结果求助
问题:Refresh Token异步函数无限运行无返回结果
我在实现Refresh Token功能时,异步函数loginUserTkRefresh无限运行且没有任何结果返回,多次检查语法、合并文件都无法解决。相关代码如下:
相关代码文件
users.js
const jwt = require("jsonwebtoken"); module.exports = { loginUserTkRefresh: async (req, res) => { const refreshToken = req.body.token if(!refreshToken) return res.status(401); try { await jwt.verify(refreshToken, process.env.REFRESH_ACCESS_TOKEN); } catch (err) { return res.sendStatus(403); } const accessToken = jwt.sign( { id: 1 }, process.env.ACCESS_TOKEN, { expiresIn: 200 } ); res.send({ accessToken }); }, };
api.js
const express = require("express"); const jwt = require("jsonwebtoken"); const router = express.Router(); const user = require("../actions/api/users"); router.get("/users", authenticate, (req, res) => { const users = [{ id: 1, email: "adam@op.pl", password: "12321" }]; res.send(users); }); router.post("/auth/login", user.loginUser); router.post("/auth/refresh", user.loginUserTkRefresh); function authenticate(req, res, next) { const authHeader = req.headers["authorization"]; const token = authHeader && authHeader.split(" ")[1]; if (token === null) return res.status(401); jwt.verify(token, process.env.ACCESS_TOKEN, (err, user) => { if (err) return res.sendStatus(403); req.user = user; next(); }); } module.exports = router;
index.js
const express = require("express"); require("dotenv").config(); const app = express(); const { port } = require("./config/config"); const apiRouter = require("./routes/api"); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // routes app.use("/api", apiRouter); // server app.listen(port, () => { console.log("Server is listening..."); console.log(`\tAddress: http://localhost:${port}`); });
请求示例
POST http://localhost:3000/api/auth/refresh Content-Type: "application/json" { "token":" " }
解决方案
问题核心:原生jsonwebtoken库的jwt.verify默认是回调式API,并非Promise对象,直接用await调用会导致代码一直处于pending状态,异步函数无法继续执行,最终表现为无限运行无返回。
提供两种修复方式:
方式1:用util.promisify包装为Promise版本
const jwt = require("jsonwebtoken"); const { promisify } = require("util"); // 将jwt.verify转换为支持await的Promise函数 const verifyToken = promisify(jwt.verify); module.exports = { loginUserTkRefresh: async (req, res) => { const refreshToken = req.body.token if(!refreshToken) return res.status(401); try { // 使用包装后的函数执行验证 await verifyToken(refreshToken, process.env.REFRESH_ACCESS_TOKEN); } catch (err) { return res.sendStatus(403); } const accessToken = jwt.sign( { id: 1 }, process.env.ACCESS_TOKEN, { expiresIn: 200 } ); res.send({ accessToken }); }, };
方式2:改用回调式逻辑处理
如果不想使用Promise,直接采用jwt.verify原生回调写法,移除async/await:
const jwt = require("jsonwebtoken"); module.exports = { loginUserTkRefresh: (req, res) => { const refreshToken = req.body.token if(!refreshToken) return res.status(401); jwt.verify(refreshToken, process.env.REFRESH_ACCESS_TOKEN, (err) => { if (err) return res.sendStatus(403); const accessToken = jwt.sign( { id: 1 }, process.env.ACCESS_TOKEN, { expiresIn: 200 } ); res.send({ accessToken }); }); }, };
额外注意:测试时请传入有效的Refresh Token,请求示例中的空格字符串会直接触发403返回。
内容的提问来源于stack exchange,提问作者Szubierski
相关产品推荐
相关产品推荐

