Express中如何使用async/await

随着Node.js v7.6.0版本开始支持async/await,在服务器端进行Node.js编程也终于有了最佳的异步解决方案。

 

只要你Node.js安装的是v7.6.x以上版本,都是支持async/await语法的。

所以只要你安装的是Node.js新版本,在Express程序里面是可以直接使用async/await方法的。

 

参考下面实例:

 

const express = require('express');
const app = express();
const fs = require('fs');
function readFileAsync(filepath) {
	return new Promise(function (resolve, reject) {
		fs.readFile(filepath, function (err, data) {
			if (err) {
				reject(err);
				return;
			}
			resolve(JSON.parse(data.toString()));
		});
	});
}
app.get('/', async (req, res, next) => {
	const data = await readFileAsync('./test.json');
	res.send(data.worlds);

});
// Error Handler
app.use(function (err, req, res, next) {
	console.error('Error:', err);
	res.status(500).send(err.message);
});
const server = app.listen(3000, () => {
	let port = server.address().port;
	console.log(`server is running on port ${port}`);
});

 

代码可以正常执行,通过实例发现不对express进行任何改造async/await也能使用,现在我们读取一个不存在的文件看看存在的问题。

 

const data = await readFileAsync('./test2.json');
 
此时会发生请求不能及时响应,过一段时间出现UnhandledPromiseRejectionWarning的错误提示,这是因为async函数里面的错误默认不能被错误中间件捕获的原因。

 

怎么才能捕获async函数里面的错误呢?

解决方法:

1,添加try/catch

app.get('/', async (req, res, next) => {
try{
   const data = await readFileAsync('./test2.json');
   res.send(data.worlds);
}catch(err){
   next(err);
}
});

 

运行发现此时错误可以被错误中间件捕获处理了,如果在所有可能出现错误的地方的都添加try/catch,代码看起来就太不优雅精简了,更好一点的方式就是写一个方法可以自动捕获async函数里面的错误。

 

2,使用Promise对象

因为async函数默认返回的是一个Promise对象,所以可以用下面的asyncHandler函数捕获async函数中出现的异常错误。

 

//执行捕获异常错误
const asyncHandler = function (fn) {
	return function (...args) {
		Promise.resolve(fn(...args)).catch(args[2]);
	}
}

app.get('/', asyncHandler(async (req, res, next) => {
	const data = await readFileAsync('./test2.json');
	res.send(data.worlds);
}));
 

 

不过这些实现代码看起来还是怪怪的,每个用到的地方都要添加asyncHandler函数,这是作为一个有追求的程序员不能忍受的,我们要追求更极致的方式。

 

3,更精简的实现方式是我们可以通过修改express的底层router来实现:

 

const Layer = require('express/lib/router/layer');
Object.defineProperty(Layer.prototype, 'handle', {
	enumerable: true,
	get() {
		return this.__handle;
	},
	set(fn) {
		if (fn.length === 4) {
			this.__handle = fn;
		} else {
			this.__handle = (req, res, next) =>
				Promise.resolve(fn(req, res, next)).catch(next);
		}
	},
});

 

 这样修改之后就可以全局捕获express路由async函数中出现的异常错误了,下面是完整的代码:

 

const express = require('express');
const app = express();
const fs = require('fs');
function readFileAsync(filepath) {
	return new Promise(function (resolve, reject) {
		fs.readFile(filepath, function (err, data) {
			if (err) {
				reject(err);
				return;
			}
			resolve(JSON.parse(data.toString()));
		});
	});
}
const Layer = require('express/lib/router/layer');
Object.defineProperty(Layer.prototype, 'handle', {
	enumerable: true,
	get() {
		return this.__handle;
	},
	set(fn) {
		if (fn.length === 4) {
			this.__handle = fn;
		} else {
			this.__handle = (req, res, next) =>
				Promise.resolve(fn(req, res, next)).catch(next);
		}
	},
});
app.get('/', async (req, res, next) => {
	const data = await readFileAsync('./test2.json');
	res.send(data.worlds);
});
// Error Handler
app.use(function (err, req, res, next) {
	console.error('Error:', err);
	res.status(500).send(err.message);
});
const server = app.listen(3000, () => {
	let port = server.address().port;
	console.log(`server is running on port ${port}`);
});

 

so easy...^_^

 

你可能感兴趣的:(技术型)