封装jsforce连接时异步获取token,链式调用实例方法报错如何解决?
问题原因
JSForce.Connect()是异步函数,它返回的是Promise对象,而非直接的jsforce连接实例。所以你直接链式调用.sobject('Account')时,实际上是在给Promise对象调用不存在的方法,自然会报错。
解决方案
你可以通过以下两种方式实现"无需提前await存实例,直接链式调用方法"的需求:
方案1:用Proxy包装Promise,自动处理异步解析
通过Proxy拦截所有方法调用,等待Promise resolve拿到连接实例后,再调用对应方法:
const force = require('jsforce') const { SFAuth } = require('./auth') const common = require('../common') class JSForce { static async getConnection() { const token = await SFAuth.getToken() return new force.Connection({ instanceUrl: common.SALESFORCE_URL, accessToken: token }) } static Connect() { // 返回一个Proxy,拦截所有方法调用 return new Proxy(this.getConnection(), { get(target, prop) { // 如果是Promise本身的方法,直接返回 if (prop in target) { return target[prop] } // 否则,返回一个函数,等待Promise resolved后调用对应方法 return async (...args) => { const connection = await target return connection[prop](...args) } } }) } } // 现在可以直接链式调用: ;(async () => { const accounts = await JSForce.Connect().sobject('Account').find({}) console.log(accounts) })()
方案2:封装单例类,自动维护token有效期与连接实例
如果想复用连接实例(避免每次调用都创建新连接),可以封装一个单例类,内部检查token是否过期,自动刷新:
const force = require('jsforce') const { SFAuth } = require('./auth') const common = require('../common') class JSForce { static #instance = null static #expiresAt = 0 // token过期时间戳 static async #getValidConnection() { // 检查token是否过期,过期则重新获取 if (Date.now() >= this.#expiresAt || !this.#instance) { const token = await SFAuth.getToken() this.#instance = new force.Connection({ instanceUrl: common.SALESFORCE_URL, accessToken: token }) // 设置过期时间(当前时间+1小时,单位毫秒) this.#expiresAt = Date.now() + 3600 * 1000 } return this.#instance } // 用Proxy直接暴露所有方法 static get Connect() { return new Proxy({}, { get(target, prop) { return async (...args) => { const connection = await this.#getValidConnection() return connection[prop](...args) } } }) } } // 使用方式: ;(async () => { const accounts = await JSForce.Connect.sobject('Account').find({}) console.log(accounts) })()
两种方案都能实现你想要的效果:无需提前保存实例,直接通过JSForce.Connect链式调用jsforce的方法,内部自动处理异步获取token、维护连接的逻辑。
内容的提问来源于stack exchange,提问作者Jordan
相关产品推荐
相关产品推荐

