这似乎是一个简单的谷歌,但我似乎无法找到答案......
您可以将ES7异步功能传递给Express路由器吗?
示例:
var express = require('express');
var app = express();
app.get('/', async function(req, res){
// some await stuff
res.send('hello world');
});
如果没有,你能指出我如何处理这个问题的正确方向ES7风格?或者我只需要使用承诺?
谢谢!
答案 0 :(得分:9)
可能是您没有找到结果,因为async/await
是 ES7 而不是ES6功能,它在节点> = 7.6中可用。
您的代码将在节点中运行。 我测试了以下代码
var express = require('express');
var app = express();
async function wait (ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms)
});
}
app.get('/', async function(req, res){
console.log('before wait', new Date());
await wait(5 * 1000);
console.log('after wait', new Date())
res.send('hello world');
});
app.listen(3000, err => console.log(err ? "Error listening" : "Listening"))
瞧
MacJamal:messialltimegoals dev$ node test.js
Listening undefined
before wait 2017-06-28T22:32:34.829Z
after wait 2017-06-28T22:32:39.852Z
^C
基本上,你得到它,你必须async
一个函数,以便await
在其代码中的承诺。
这在节点LTS v6中不受支持,因此可能使用babel来转换代码。
希望这会有所帮助。
答案 1 :(得分:3)
虽然看起来可行,但它会停止处理异步函数中引发的错误,结果,如果未处理错误,则服务器将永远不会响应,客户端会一直等待直到超时。
正确的行为应该是使用 500 状态码进行响应。
const router = require('express-promise-router')();
// Use it like a normal router, it will handle async functions
const asyncify = require('express-asyncify')
app
对象中设置的路由将var app = express();
替换为
var app = asyncify(express());
router
个对象中设置的路由将var router = express.Router();
替换为
var router = asyncify(express.Router());
您只需要在直接设置路径的对象中应用asyncify
函数
答案 2 :(得分:2)
我认为你不能直接这样做,因为没有捕获异常,如果抛出异常,函数将不会返回。本文介绍如何创建包装函数以使其工作:http://thecodebarbarian.com/using-async-await-with-mocha-express-and-mongoose.html
我没有尝试过,但最近正在调查此事。
答案 3 :(得分:0)
const express = require('express');
const Router = require('express-promise-router');
const router = new Router();
const mysql = require('mysql2');
const pool = mysql.createPool({
host: 'localhost',
user: 'myusername',
password: 'mypassword',
database: 'mydb',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
}).promise();
router.get('/some_path', async function(req, res, next) {
const [rows, ] = await pool.execute(
'SELECT * ' +
'FROM mytable ',
[]
);
res.json(rows);
});
module.exports = router;
(以上是在express-promise-router
上使用mysql2的promise接口的示例。)
答案 4 :(得分:0)
要处理快速路由中的异步请求,请使用try catch,它可以帮助您尝试功能中的任何错误并加以捕获。 try{await stuff} catch{err}
答案 5 :(得分:0)
Express 5 会自动为您处理 async
个错误
https://expressjs.com/en/guide/error-handling.html 目前明确表示:
<块引用>从 Express 5 开始,返回 Promise 的路由处理程序和中间件将在拒绝或抛出错误时自动调用 next(value)。例如:
app.get('/user/:id', async function (req, res, next) {
var user = await getUserById(req.params.id)
res.send(user)
})
如果 getUserById 抛出错误或拒绝,next 将使用抛出的错误或拒绝的值调用。如果没有提供拒绝值,next 将使用 Express 路由器提供的默认 Error 对象调用。
我们可以进行如下测试:
const assert = require('assert')
const http = require('http')
const express = require('express')
const app = express()
app.get('/error', async (req, res) => {
throw 'my error'
})
const server = app.listen(3000, () => {
// Test it.
function test(path, method, status, body) {
const options = {
hostname: 'localhost',
port: server.address().port,
path: path,
method: method,
}
http.request(options, res => {
console.error(res.statusCode);
assert(res.statusCode === status);
}).end()
}
test('/error', 'GET', 500)
})
express@5.0.0-alpha.8
上的终端输出是预期的:
500
Error: my error
at /home/ciro/test/express5/main.js:10:9
at Layer.handle [as handle_request] (/home/ciro/test/node_modules/router/lib/layer.js:102:15)
at next (/home/ciro/test/node_modules/router/lib/route.js:144:13)
at Route.dispatch (/home/ciro/test/node_modules/router/lib/route.js:109:3)
at handle (/home/ciro/test/node_modules/router/index.js:515:11)
at Layer.handle [as handle_request] (/home/ciro/test/node_modules/router/lib/layer.js:102:15)
at /home/ciro/test/node_modules/router/index.js:291:22
at Function.process_params (/home/ciro/test/node_modules/router/index.js:349:12)
at next (/home/ciro/test/node_modules/router/index.js:285:10)
at Function.handle (/home/ciro/test/node_modules/router/index.js:184:3)
如果您在浏览器上访问它,您将看到一个显示 my error
的 HTML 页面。
如果您在 express@4.17.1 上运行完全相同的代码,您只会在终端上看到:
UnhandledPromiseRejectionWarning: my error
但不是 500
或 my error
。这是因为请求永远挂起。如果您尝试在浏览器中打开它,您会更清楚地看到它。
TODO:如何让它也显示堆栈跟踪,而不仅仅是my error
? Getting the stack trace in a custom error handler in Express?
Express 4 解决方案
Express 4 最简单的解决方案是将每条路线包装在 try
/catch
中,如下所示:
app.get('/error', async (req, res, next) => {
try {
throw new Error('my error'
res.send('never returned')
} catch(error) {
next(error);
}
})
产生与 Express 5 相同的正确行为。
您还可以使用以下讨论的一些方法进一步解决这个问题:express.js async router and error handling
在 Node.js v14.16.0 上测试。