如何通过Proxy在执行其他方法前自动调用connect方法?
如何用Proxy实现调用TelegramClient实例方法前自动执行connect?
我希望调用TelegramClient类的所有其他实例方法前,先自动执行connect方法,但目前的Proxy代码里connect并未被调用。
原代码如下:
class TelegramClient { async connect() { console.log("Connecting to Telegram..."); // 模拟异步操作 await new Promise(resolve => setTimeout(resolve, 1000)); console.log("Connected!"); } sendMessage(message: string) { console.log(`Sending message: ${message}`); } } const telegramClient = new TelegramClient(); // 创建Telegram客户端的Proxy const proxiedTelegramClient = new Proxy(telegramClient, { async apply(target, thisArg, argumentsList) { await target.connect(); // 调用方法前先连接Telegram const result = Reflect.apply(target, thisArg, argumentsList); return result; }, }); proxiedTelegramClient.sendMessage("Hello, Telegram!");
预期输出:
Connecting to Telegram... Connected! Sending message: Hello, Telegram!
问题原因
你用的apply陷阱只负责拦截函数的直接调用(比如proxy()这种形式),而调用对象的方法(proxy.sendMessage())分为两步:首先通过get操作获取sendMessage属性,然后才会执行这个函数。所以你的apply陷阱根本没被触发,自然不会调用connect。
解决方案:使用get陷阱拦截方法访问
我们需要在get陷阱里拦截方法属性的访问,返回一个包装函数,先执行connect(可以加个标记避免重复连接),再执行原方法。
修改后的代码:
class TelegramClient { private _isConnected = false; // 标记是否已连接 async connect() { if (this._isConnected) return; // 避免重复连接 console.log("Connecting to Telegram..."); await new Promise(resolve => setTimeout(resolve, 1000)); console.log("Connected!"); this._isConnected = true; } sendMessage(message: string) { console.log(`Sending message: ${message}`); } } const telegramClient = new TelegramClient(); const proxiedTelegramClient = new Proxy(telegramClient, { get(target, prop) { const originalProp = Reflect.get(target, prop); // 如果访问的是方法,且不是connect本身 if (typeof originalProp === 'function' && prop !== 'connect') { // 返回包装后的异步函数 return async function(...args) { await target.connect(); // 先执行连接 // 绑定原方法的this,再调用 return originalProp.apply(target, args); } } return originalProp; } }); // 测试调用 proxiedTelegramClient.sendMessage("Hello, Telegram!"); // 第二次调用不会重复连接 proxiedTelegramClient.sendMessage("Second message!");
关键点说明
- 添加连接状态标记:给
TelegramClient加_isConnected属性,避免每次调用方法都重复执行connect,符合实际场景(连接只需要一次)。 get陷阱拦截方法:当访问的属性是函数且不是connect时,返回一个包装函数,先执行connect再调用原方法。- 绑定this上下文:用
apply确保原方法执行时this指向原始实例,避免上下文丢失。
执行后输出符合预期:
Connecting to Telegram... Connected! Sending message: Hello, Telegram! Sending message: Second message!
内容的提问来源于stack exchange,提问作者kabdik
相关产品推荐
相关产品推荐

