开发笔记: ethers.js 与 vue3 共同使用时报错 `TypeError: 'get' on proxy: property '_network' i

454 阅读1分钟

ethers.js 与 vue3 共同使用时报错 TypeError: 'get' on proxy: property '_network' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '#<Object>' but got '#<Object>')

类似错误复现路径:

// 0. 定义对象obj
const obj = {
  b: '456'
}

// 1. 将属性b定义为 configurable false, writable false
Object.defineProperty(obj, 'b', {
  configurable: false,
  writable: false,
  value: '777'
})


// 2. proxy 对象返回的 属性b的值 与原对象不符
// 注:步骤1和2可以颠倒顺序
const proxy = new Proxy(obj, {
  get() {
    return 'biubiubiu'
  }
})


// 3. 报错: Uncaught TypeError: 'get' on proxy: property 'b' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '777' but got 'biubiubiu') 
console.log(proxy.b)

报错原因

  1. 在初始化Provider实例时,_network属性被定义为 readonly. defineReadOnly(this, "_network", knownNetwork);

defineReadOnly 定义如下:

function defineReadOnly(object, name, value) {

  // configurable 属性默认为false
  Object.defineProperty(object, name, {
    enumerable: true,
    value,
    writable: false
  });
}
  1. 把Provider实例赋值给Ref时,Provider实例被转换成一个Proxy实例,它修改了get方法,使_network属性返回的是一个改造后的Proxy实例,而不是原_network,所以报错。
const address = 'xxxx' // omitted

const provider = ref<ethers.providers.Web3Provider>()

provider.value = new ethers.providers.Web3Provider((window as any).ethereum, chainId)

// 报错,getBalance内部会访问_network属性
provider.value.getBalance(address)

修复方案

替换 RefShallowRef