详解如何让Express支持async/await

2020-06-17 07:05:51易采站长站整理

const app = express();
const router = new express.Router();
app.use(router);

app.get = function (...data){
const params = [];
for (let item of data) {
if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') {
params.push(item);
continue;
}
const handle = function (...data){
const [ req, res, next ] = data;
item(req, res, next).then(next).catch(next);
};
params.push(handle);
}
router.get(...params)
}

像上面这样改造之后似乎一切都能正常工作了,能正常处理请求了。但通过查看 Express 的源码,发现这样破坏了 app.get() 这个方法,因为 app.get() 不仅能用来处理路由,而且还能用来获取应用的配置,在 Express 中对应的源码如下:


methods.forEach(function(method){
app[method] = function(path){
if (method === 'get' && arguments.length === 1) {
// app.get(setting)
return this.set(path);
}

this.lazyrouter();

var route = this._router.route(path);
route[method].apply(route, slice.call(arguments, 1));
return this;
};
});

所以在改造时,我们也需要对 app.get 做特殊处理。在实际的应用中我们不仅有 get 请求,还有 post、put 和 delete 等请求,所以我们最终改造的代码如下:


const { promisify } = require('util');
const { readFile } = require('fs');
const readFileAsync = promisify(readFile);
const express = require('express');
const app = express();
const router = new express.Router();
const methods = [ 'get', 'post', 'put', 'delete' ];
app.use(router);

for (let method of methods) {
app[method] = function (...data){
if (method === 'get' && data.length === 1) return app.set(data[0]);

const params = [];
for (let item of data) {
if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') {
params.push(item);
continue;
}
const handle = function (...data){
const [ req, res, next ] = data;
item(req, res, next).then(next).catch(next);
};
params.push(handle);
}
router[method](...params);
};
}

app.get('/', async function (req, res, next){
const data = await readFileAsync('./package.json');
res.send(data.toString());
});

app.post('/', async function (req, res, next){
const data = await readFileAsync('./age.json');
res.send(data.toString());
});

router.use(function (err, req, res, next){
console.error('Error:', err);
res.status(500).send('Service Error');
});

app.listen(3000, '127.0.0.1', function (){
console.log(`Server running at http://${this.address().address }:${this.address().port }/`);
});