如何不使用async/await,在Promise完成后用Immer.js修改draft对象
问题原因
报错本质是Immer的draft代理生命周期规则导致的:
- 当你给
produce传入同步函数时,Immer会在函数同步执行结束后立刻销毁(revoke)draft代理对象,后续任何对该draft的操作都会触发illegal operation attempted on a revoked proxy错误。 - async/await写法能正常运行,是因为async函数默认返回Promise,Immer内置支持异步producer:如果
produce检测到回调返回Promise,会等该Promise决议完成后再销毁draft代理。 - 第二个写法的问题在于:produce的回调里只是启动了异步Promise链,但没有把这个Promise返回给produce,produce认为回调同步执行完毕就直接销毁了draft,等
Promise.resolve(5).then触发修改draft的时候,代理已经失效了。
修改方案
只要在produce的回调里把你构造的Promise链返回即可,让Immer感知到有异步逻辑需要等待:
import produce from 'immer'; Promise.resolve({ eggs: 0 }).then( produce((eggCounter) => { // 返回Promise,让Immer等待异步逻辑完成后再销毁draft return Promise.resolve(5).then((n) => eggCounter.eggs += n) }) ).then(console.log)
效果验证
修改后代码运行逻辑和async/await版本完全等价,最终会输出{ eggs: 5 },不会再触发代理撤销错误。
内容的提问来源于stack exchange,提问作者pixatlazaki
相关产品推荐
相关产品推荐

