在前端开发中,JSON 序列化是非常常见的操作,可以用于数据传输、储存等多种场景。在 ES8(ECMAScript 2017)中,新引入了“异步迭代器”(async iterators)功能,极大的扩展了 JavaScript 的异步编程能力。但同时也带来了 JSON 序列化的缺陷,本文将介绍这个缺陷的具体表现、解决的方案以及示例代码。
JSON 序列化缺陷表现
在 ES8 中,JSON.stringify 函数的参数默认会调用对象的内置的 @@asyncIterator 方法进行遍历。而对于不含 @@asyncIterator 方法的对象,则直接调用其默认迭代器 Iterator 进行遍历。
对于含有 @@asyncIterator 方法的对象,如果在序列化时需要等待其异步迭代工作完成,即非同步操作,那么该部分数据将不能被序列化输出。JSON 算法中不支持异步操作,会直接抛出 TypeError 错误。
举个例子:
// javascriptcn.com 代码示例 const obj = { name: 'Tom', age: 18, // 含有异步迭代器的属性 async *[Symbol.asyncIterator]() { yield this.name; yield this.age; } }; JSON.stringify(obj); // TypeError: Converting [object AsyncGenerator] to JSON is not supported
解决方案
解决这个问题的方法,是在对象上绑定 toJSON 方法。toJSON 方法定义,可以将一个 JavaScript 对象序列化为 JSON 字符串的过程自定义。所以,我们可以在 toJSON 方法中手动处理异步迭代器,并返回同步的对象进行序列化。
下面是一个示例:
// javascriptcn.com 代码示例 const obj = { name: 'Tom', age: 18, // 含有异步迭代器的属性 async *[Symbol.asyncIterator]() { yield this.name; yield this.age; }, // 手动处理异步迭代器,返回同步对象 async toJSON() { let result = {}; const keys = Object.getOwnPropertyNames(this); for (let key of keys) { const value = this[key]; if (value && typeof value[Symbol.asyncIterator] === 'function') { const arr = []; for await (let item of value) { arr.push(item); } result[key] = arr; } else { result[key] = value; } } return result; } }; JSON.stringify(obj); // "{"name":"Tom","age":18}"
在 toJSON 方法中,我们首先获取所有属性名,然后遍历所有属性。如果属性值含有异步迭代器,则手动触发异步迭代,等待其操作全部完成后返回同步的值,最后将之前 stringify 无法处理的异步迭代器属性同步到对象中,再进行序列化。
总结
以上就是关于 ES8 中 JSON 序列化缺陷修复方案的介绍和示例代码。尽管这个缺陷并不常见,但是权益自己的编程能力,了解这种情况并熟知其解决方案,有助于对问题的深入理解、提高代码水平,同时增加实际工作中的应用足以简化代码逻辑,提高代码健壮性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/653243537d4982a6eb4b2117