在 TypeScript 的 Koa 调试模式下,如何使自定义中间件函数记录到控制台?
How do I make a custom middleware function get logged to console while in Koa debug mode in TypeScript?
使用 Koa v2.7.0 和 TypeScript v3.3.1
我的 "errorHandler" 中间件函数是这样导出的
export const clientErrorHandler = () => {
return async (ctx: Context, next: NextFunction) => {
try{
await next();
}
catch (err){
if(err instanceof HTTPClientError){
console.warn(err);
ctx.status = err.statusCode;
ctx.body = err.message;
ctx.app.emit('error', err, ctx);
}
}
}
}
我在给定 Koa 应用程序上处理中间件附件的逻辑如下所示:
export const handleErrors = (app: Koa) => {
const serverErrHandler = serverErrorHandler();
serverErrHandler._name = 'serverErrorHandler';
app.use(serverErrHandler)
}
我尝试创建此 属性 的原因是由于此 Koa 文档(请参阅下面的 link),其中指出我们可以为中间件函数提供一个 _name 属性这样当我们 运行 设置了 DEBUG=koa*
的程序时,这个中间件函数将能够有一个显示在控制台中的名称。
Since JavaScript does not allow defining function names at runtime,
you can also set a middleware's name as ._name. This is useful when
you don't have control of a middleware's name. For example:
const path = require('path'); const serve = require('koa-static');
const publicFiles = serve(path.join(__dirname, 'public'));
publicFiles._name = 'static /public';
app.use(publicFiles);
Source of the above snippet: https://github.com/koajs/koa/blob/master/docs/guide.md#debugging-koa
但是,在尝试此操作时,由于我使用的是 TypeScript,它不喜欢我尝试在此匿名函数上设置 属性。
[ts] Property '_name' does not exist on type '(ctx: Context, next:
NextFunction) => Promise'.
我希望确定使自己能够将这个小 _name
属性 添加到这个匿名函数的最佳方法,以便我可以获得可靠的调试日志。
当我写这篇文章时,我最终找到了两个可能的解决方案。
我要使用的方法是不使用匿名函数,因此无需修改我的中间件函数上的 _name
属性。重新阅读 koa 文档后,我认为我查看的关键词是
"for middleware that you don't have control over"
我的中间件函数定义现在看起来像这样:
export const clientErrorHandler = () => {
let clientErrHandler = async (ctx: Context, next: NextFunction) => {
try{
await next();
}
catch (err){
if(err instanceof HTTPClientError){
console.warn(err);
ctx.status = err.statusCode;
ctx.body = err.message;
ctx.app.emit('error', err, ctx);
}
}
}
return clientErrHandler;
}
现在,如果假设这是您无法控制第三方中间件函数名称并且您使用的是 TypeScript 的情况,我发现这个堆栈溢出解决方案在这种情况下有帮助:
使用 Whosebug 的建议,可以定义一个接口并使用匿名函数进行类型断言,以产生一个结果,让调用者打字稿代码设置 _name
属性 returned 功能没有抱怨没有这样的 属性 存在。
只是为了演示它的样子:
尽管我在您技术上无法修改的代码上进行演示,但我假设您也可以在调用方进行类型断言,然后修改 _name
属性之后。
interface MiddlewareFunction { (ctx: Context, next: NextFunction ): Promise<void>; _name: string; }
export const serverErrorHandler = () => {
return <MiddlewareFunction> async function (ctx: Context, next: NextFunction){
try {
await next();
}
catch (err) {
if(process.env.NODE_ENV === 'production'){
ctx.status = 500;
ctx.body = 'Internal Server Error';
}
else {
ctx.status = err.status;
ctx.body = err.stack;
ctx.app.emit('error', err, ctx);
}
}
}
}
与问题中的代码相同:
export const handleErrors = (app: Koa) => {
const serverErrHandler = serverErrorHandler();
serverErrHandler._name = 'serverErrorHandler';
app.use(serverErrHandler)
}
编辑:您也可以在 return.
中将箭头函数改回正常的 javascript 函数
export const serverErrorHandler = () => {
return async function serverErrorHandler (ctx: Context, next: NextFunction){
try {
await next();
}
catch (err) {
if(process.env.NODE_ENV === 'production'){
ctx.status = 500;
ctx.body = 'Internal Server Error';
}
else {
ctx.status = err.status;
ctx.body = err.stack;
ctx.app.emit('error', err, ctx);
}
}
}
}
使用 Koa v2.7.0 和 TypeScript v3.3.1
我的 "errorHandler" 中间件函数是这样导出的
export const clientErrorHandler = () => {
return async (ctx: Context, next: NextFunction) => {
try{
await next();
}
catch (err){
if(err instanceof HTTPClientError){
console.warn(err);
ctx.status = err.statusCode;
ctx.body = err.message;
ctx.app.emit('error', err, ctx);
}
}
}
}
我在给定 Koa 应用程序上处理中间件附件的逻辑如下所示:
export const handleErrors = (app: Koa) => {
const serverErrHandler = serverErrorHandler();
serverErrHandler._name = 'serverErrorHandler';
app.use(serverErrHandler)
}
我尝试创建此 属性 的原因是由于此 Koa 文档(请参阅下面的 link),其中指出我们可以为中间件函数提供一个 _name 属性这样当我们 运行 设置了 DEBUG=koa*
的程序时,这个中间件函数将能够有一个显示在控制台中的名称。
Since JavaScript does not allow defining function names at runtime, you can also set a middleware's name as ._name. This is useful when you don't have control of a middleware's name. For example:
const path = require('path'); const serve = require('koa-static');
const publicFiles = serve(path.join(__dirname, 'public'));
publicFiles._name = 'static /public';
app.use(publicFiles);
Source of the above snippet: https://github.com/koajs/koa/blob/master/docs/guide.md#debugging-koa
但是,在尝试此操作时,由于我使用的是 TypeScript,它不喜欢我尝试在此匿名函数上设置 属性。
[ts] Property '_name' does not exist on type '(ctx: Context, next: NextFunction) => Promise'.
我希望确定使自己能够将这个小 _name
属性 添加到这个匿名函数的最佳方法,以便我可以获得可靠的调试日志。
当我写这篇文章时,我最终找到了两个可能的解决方案。
我要使用的方法是不使用匿名函数,因此无需修改我的中间件函数上的 _name
属性。重新阅读 koa 文档后,我认为我查看的关键词是
"for middleware that you don't have control over"
我的中间件函数定义现在看起来像这样:
export const clientErrorHandler = () => {
let clientErrHandler = async (ctx: Context, next: NextFunction) => {
try{
await next();
}
catch (err){
if(err instanceof HTTPClientError){
console.warn(err);
ctx.status = err.statusCode;
ctx.body = err.message;
ctx.app.emit('error', err, ctx);
}
}
}
return clientErrHandler;
}
现在,如果假设这是您无法控制第三方中间件函数名称并且您使用的是 TypeScript 的情况,我发现这个堆栈溢出解决方案在这种情况下有帮助:
使用 Whosebug 的建议,可以定义一个接口并使用匿名函数进行类型断言,以产生一个结果,让调用者打字稿代码设置 _name
属性 returned 功能没有抱怨没有这样的 属性 存在。
只是为了演示它的样子:
尽管我在您技术上无法修改的代码上进行演示,但我假设您也可以在调用方进行类型断言,然后修改 _name
属性之后。
interface MiddlewareFunction { (ctx: Context, next: NextFunction ): Promise<void>; _name: string; }
export const serverErrorHandler = () => {
return <MiddlewareFunction> async function (ctx: Context, next: NextFunction){
try {
await next();
}
catch (err) {
if(process.env.NODE_ENV === 'production'){
ctx.status = 500;
ctx.body = 'Internal Server Error';
}
else {
ctx.status = err.status;
ctx.body = err.stack;
ctx.app.emit('error', err, ctx);
}
}
}
}
与问题中的代码相同:
export const handleErrors = (app: Koa) => {
const serverErrHandler = serverErrorHandler();
serverErrHandler._name = 'serverErrorHandler';
app.use(serverErrHandler)
}
编辑:您也可以在 return.
中将箭头函数改回正常的 javascript 函数export const serverErrorHandler = () => {
return async function serverErrorHandler (ctx: Context, next: NextFunction){
try {
await next();
}
catch (err) {
if(process.env.NODE_ENV === 'production'){
ctx.status = 500;
ctx.body = 'Internal Server Error';
}
else {
ctx.status = err.status;
ctx.body = err.stack;
ctx.app.emit('error', err, ctx);
}
}
}
}