在高阶函数(nestjs)中未定义 this

发布于 2025-01-12 17:04:03 字数 738 浏览 2 评论 0原文

我正在尝试实现一些基本的高阶函数,它将返回一个新函数,其中提供的函数被 try catch 块包围。像这样的事情:

function wrapLogging(f) {
    return async (...args) => {
        try {
            await f(...args);
        } catch (e) {
           log(e);
    };
  }
}

// dummy example:

const executeAndLog = wrapLogging(executeFunction);
executeAndLog();


// nestjs controller and service example:

 @Post('/create')
   async executeAndLog() {
       const executeAndLog = wrapLogging(this.exampleService.create);
       await executeAndLog();
  }

现在的问题是我在提供的 this.exampleService.create 中遇到未定义的错误。 “类型错误:无法读取未定义的属性...” 我确实知道上下文缺失,但不知道如何“连接”它。尝试谷歌搜索示例并发现 .call 或 .apply 解决方案存在类似问题,但在这种情况下不起作用。也许是因为提供的服务方法是异步的,或者与nestjs服务及其上下文有关?

非常感谢任何帮助!蒂

I'm trying to implement some basic higher order function which would return a new function with provided function surrounded with try catch block. Something like this:

function wrapLogging(f) {
    return async (...args) => {
        try {
            await f(...args);
        } catch (e) {
           log(e);
    };
  }
}

// dummy example:

const executeAndLog = wrapLogging(executeFunction);
executeAndLog();


// nestjs controller and service example:

 @Post('/create')
   async executeAndLog() {
       const executeAndLog = wrapLogging(this.exampleService.create);
       await executeAndLog();
  }

Now the problem is that I get undefined errors in provided this.exampleService.create.
"TypeError: Cannot read properties of undefined..."
I do get that the context is missing but don't know how to 'connect' it. Tried googling examples and found similar problem with .call or .apply solutions but it didn't work in this case. Maybe it's because the service method provided is async, or it's something to do with nestjs services and their context?

any help is greatly appreciated! ty

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陌生 2025-01-19 17:04:03

要使用这样的方法,您需要认识到在使用函数时词法this会丢失。您可以使用 .bind() 将正确的 this 重新绑定到该方法,以便您仍然可以在该方法内使用 this。以下内容可以保留 this 但允许您包装方法

app.controller.ts

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

function wrapLogging(f: (...args: any[]) => any) {
  console.log('Calling method');
  console.log(f);
  return async (...args) => {
    try {
      return await f(...args);
    } catch (e) {
      console.log(e);
    }
  };
}

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  async getHello(): Promise<string> {
    const method = wrapLogging(this.appService.getHello.bind(this.appService));
    return method();
  }
}

app.service.ts

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  private greeting = 'Hello World!';
  getHello(): string {
    console.log('Returning greeting');
    console.log(this);
    return this.greeting;
  }
}

HTTP 调用

xh :3000
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 12
Content-Type: text/plain; charset=utf-8
Date: Tue, 08 Mar 2022 16:01:19 GMT
Keep-Alive: timeout=5

Hello World!

日志

Calling method
[Function: bound getHello]
Returning greeting
AppService { greeting: 'Hello World!' }

我建议采用装饰器的路线并修改 描述符。 value 而不是单独的函数,因为每次您想要包装方法时都需要执行此 bind 操作,但最终取决于您。

To use an approach like this, you need to recognize that the lexical this gets lost when using functions. You can use .bind() to rebind the proper this to the method, so that you can still use this inside the method. The following works in keeping this but allowing you to wrap your methods

app.controller.ts

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

function wrapLogging(f: (...args: any[]) => any) {
  console.log('Calling method');
  console.log(f);
  return async (...args) => {
    try {
      return await f(...args);
    } catch (e) {
      console.log(e);
    }
  };
}

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  async getHello(): Promise<string> {
    const method = wrapLogging(this.appService.getHello.bind(this.appService));
    return method();
  }
}

app.service.ts

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  private greeting = 'Hello World!';
  getHello(): string {
    console.log('Returning greeting');
    console.log(this);
    return this.greeting;
  }
}

HTTP call

xh :3000
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 12
Content-Type: text/plain; charset=utf-8
Date: Tue, 08 Mar 2022 16:01:19 GMT
Keep-Alive: timeout=5

Hello World!

logs

Calling method
[Function: bound getHello]
Returning greeting
AppService { greeting: 'Hello World!' }

I would suggest going the route of a decorator and modifying the descriptor.value instead of a separate function, as you'll need to do this bind every time you want to wrap your method, but in the end it's up to you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文