能否利用JSON.stringify的replacer函数获取Promise解析值?
如何序列化包含Promise实例的JSON对象?
我有一个需要序列化的JSON对象,其中部分值是Promise实例。想让JSON.stringify()使用Promise的解析结果而非Promise本身进行序列化,但直接调用得到的结果不符合预期。
示例场景
现有如下对象:
const data = { foo: "foo", get bar() { return Promise.resolve('bar') }, get baz() { return 'baz' }, }
直接调用JSON.stringify(data)得到的结果是:
{"foo":"foo","bar":{},"baz":"baz"}
但我希望bar的值是"bar",和baz的结果一致。
为什么async/await版replacer不生效?
我尝试过用带async/await的replacer函数,但没有效果:
const data = { foo: "foo", get bar() { return Promise.resolve('bar') }, get baz() { return 'baz' }, } const text = JSON.stringify(data, async(key, value) => { return value instanceof Promise ? await value : value }) console.log(text) // 依然输出 {"foo":"foo","bar":{},"baz":"baz"}
原因很简单:JSON.stringify()是同步执行的,replacer函数返回的Promise会被当成普通对象处理,无法等待其解析完成。
正确解决方案
要实现需求,必须先把对象中所有的Promise都解析完成,得到一个完全同步的对象,再调用JSON.stringify()。
基础版(处理单层对象)
const data = { foo: "foo", get bar() { return Promise.resolve('bar') }, get baz() { return 'baz' }, } // 解析对象中的所有Promise,返回纯同步对象 async function resolvePromises(obj) { const result = {} for (const key of Object.keys(obj)) { let value = obj[key] // 处理Promise值 if (value instanceof Promise) { result[key] = await value } else { result[key] = value } } return result } // 执行流程 resolvePromises(data).then(resolvedData => { const jsonStr = JSON.stringify(resolvedData) console.log(jsonStr) // 输出 {"foo":"foo","bar":"bar","baz":"baz"} })
增强版(支持嵌套对象/数组)
如果对象存在嵌套结构或数组中包含Promise,可以用递归方式处理:
async function resolvePromises(obj) { // 先处理自身是Promise的情况 if (obj instanceof Promise) { return await obj } // 非对象类型直接返回 if (typeof obj !== 'object' || obj === null) { return obj } // 处理数组 if (Array.isArray(obj)) { return Promise.all(obj.map(item => resolvePromises(item))) } // 处理普通对象 const result = {} for (const key of Object.keys(obj)) { result[key] = await resolvePromises(obj[key]) } return result } // 测试嵌套场景 const nestedData = { foo: Promise.resolve('foo'), nested: { bar: Promise.resolve('bar'), list: [1, Promise.resolve(2), 3] } } resolvePromises(nestedData).then(resolved => { console.log(JSON.stringify(resolved)) // 输出 {"foo":"foo","nested":{"bar":"bar","list":[1,2,3]}} })
内容的提问来源于stack exchange,提问作者Potherca
相关产品推荐
相关产品推荐

