You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ssh2-sftp-client传递客户端函数为参数时抛出错误求助

问题:ssh2-sftp-client包装函数调用时出现上下文丢失错误

用TypeScript结合ssh2-sftp-client连接SFTP服务器,连接本身正常,但编写了包含connect和end方法的包装函数包裹主函数调用时,被调用的主函数出现错误。

相关代码

包装函数

private async session(callback: Function, ...args): Promise<any> {
    let output;

    await this.sftpClient.connect(credentials);

    try {
      output = await callback(...args);
    } catch (err) {
      throw err;
    } finally {
      await this.sftpClient.end();
    }

    return output;
}

调用函数

async getFilesList(path: string): Promise<object[]> {
      return await this.session(this.sftpClient.list, path);
}

错误信息

直接传递this.sftpClient.list作为回调时收到的错误:

list: Error removing temp listeners: Cannot read properties of null (reading 'removeListener')

尝试用output = await callback.apply(this, args)修改包装函数后,出现另一个错误:

list: Error removing temp listeners: Cannot read properties of undefined (reading 'end')

但直接在包装函数中调用this.sftpClient.list(...args)时运行正常。

问题原因

核心问题是函数上下文丢失:

  • 当直接传递this.sftpClient.list作为回调时,这个方法与原sftpClient实例解绑,调用时this不再指向sftpClient实例,导致内部操作找不到所需的属性(比如removeListener依赖的对象)。
  • 使用callback.apply(this, args)时,this指向的是当前类的实例(而非sftpClient),所以sftpClient.list内部调用end方法时找不到对应属性,报错。

解决方案

方案1:用箭头函数绑定上下文

修改调用代码,通过箭头函数确保list方法的this始终指向sftpClient实例:

async getFilesList(path: string): Promise<object[]> {
  return await this.session(() => this.sftpClient.list(path));
}

方案2:用bind绑定上下文

传递回调时,用bind方法将list的上下文固定为sftpClient实例:

async getFilesList(path: string): Promise<object[]> {
  return await this.session(this.sftpClient.list.bind(this.sftpClient), path);
}

方案3:优化包装函数支持上下文传递

如果需要包装函数适配更多场景,可以添加上下文参数,调用回调时指定正确的this:

private async session(context: any, callback: Function, ...args): Promise<any> {
    let output;
    await this.sftpClient.connect(credentials);
    try {
      // 用call指定回调的上下文
      output = await callback.call(context, ...args);
    } catch (err) {
      throw err;
    } finally {
      await this.sftpClient.end();
    }
    return output;
}

// 调用时传入sftpClient作为上下文
async getFilesList(path: string): Promise<object[]> {
  return await this.session(this.sftpClient, this.sftpClient.list, path);
}

内容的提问来源于stack exchange,提问作者dandgore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 15:01:10