如何在javascript中以异步方式解析和字符串化
Posted
技术标签:
【中文标题】如何在javascript中以异步方式解析和字符串化【英文标题】:How to parse or Stringify in asycnhronous way in javascript 【发布时间】:2018-03-20 16:07:48 【问题描述】:我看到 JSON.stringify 和 JSON.parse 都是同步的。
我想知道是否有一个简单的 npm 库以异步方式执行此操作。
谢谢
【问题讨论】:
看看这个 - npmjs.com/package/json-parse-async 从源头来看,这个库似乎没有做任何异步操作。 JSON.parse 在主线程中并且确实阻塞了事件循环。 javascript 不是多线程的......它只是交换执行机会 【参考方案1】:您可以使用 Promises 使任何东西“异步”:
function asyncStringify(str)
return new Promise((resolve, reject) =>
resolve(JSON.stringify(str));
);
然后你可以像使用任何其他承诺一样使用它:
asyncStringfy(str).then(ajaxSubmit);
请注意,由于代码不是异步的,因此 promise 将立即被解析(对 JSON 进行字符串化没有阻塞操作,不需要任何系统调用)。
如果您的平台支持,您也可以使用 async/await API:
async function asyncStringify(str)
return JSON.stringify(str);
那么你就可以用同样的方式来使用它了:
asyncStringfy(str).then(ajaxSubmit);
// or use the "await" API
const strJson = await asyncStringify(str);
ajaxSubmit(strJson);
已编辑: 添加真正的异步解析/字符串化(可能是因为我们解析的东西太复杂)的一种方法是将作业传递给另一个进程(或服务)并等待响应。
您可以通过多种方式做到这一点(比如创建一个共享 REST API 的新服务),我将在这里演示一种通过进程之间的消息传递来做到这一点的方法:
首先创建一个负责解析/字符串化的文件。为了示例,将其称为 async-json.js:
// async-json.js
function stringify(value)
return JSON.stringify(value);
function parse(value)
return JSON.parse(value);
process.on('message', function(message)
let result;
if (message.method === 'stringify')
result = stringify(message.value)
else if (message.method === 'parse')
result = parse(message.value);
process.send( callerId: message.callerId, returnValue: result );
);
这个过程所做的就是等待一条消息,要求对 JSON 进行字符串化或解析,然后以正确的值进行响应。 现在,在您的代码上,您可以分叉此脚本并来回发送消息。每当发送请求时,您都会创建一个新的 Promise,每当响应返回到该请求时,您就可以解决该 Promise:
const fork = require('child_process').fork;
const asyncJson = fork(__dirname + '/async-json.js');
const callers = ;
asyncJson.on('message', function(response)
callers[response.callerId].resolve(response.returnValue);
);
function callAsyncJson(method, value)
const callerId = parseInt(Math.random() * 1000000);
const callPromise = new Promise((resolve, reject) =>
callers[callerId] = resolve: resolve, reject: reject ;
asyncJson.send( callerId: callerId, method: method, value: value );
);
return callPromise;
function JsonStringify(value)
return callAsyncJson('stringify', value);
function JsonParse(value)
return callAsyncJson('parse', value);
JsonStringify( a: 1 ).then(console.log.bind(console));
JsonParse(' "a": "1" ').then(console.log.bind(console));
注意:这只是一个例子,但是知道了这一点,您可以找出其他改进或其他方法来做到这一点。希望这会有所帮助。
【讨论】:
谢谢。但是您在代码中调用 JSON.stringify .. 它是否使代码异步?? 解析呢? @Mark_M 解析是一样的,只需将stringify
更改为parse
。
但这并不能真正让它异步——它不只是将阻塞延迟到下一个事件循环。如果目标是在不阻塞的情况下解析大型 JSON 对象,我认为这没有帮助。
@NgendLio 节点运行阻塞的异步代码,所以它实际上不会是异步的,因为stringify
是一种“全内存算法”,它不执行任何系统调用,它永远不会阻塞事件循环。如果您确实需要异步完成或解释目标,您可以使用流程和消息传递,并且可能会更简单的解决方案(稍后我将使用真正的异步编辑我的响应)【参考方案2】:
看看这个,另一个 npm 包-
async-json is a library that provides an asynchronous version of the standard JSON.stringify.
安装-
npm install async-json
例子-
var asyncJSON = require('async-json');
asyncJSON.stringify( some: "data" , function (err, jsonValue)
if (err)
throw err;
jsonValue === '"some":"data"';
);
注意-没有测试,你需要手动检查它的依赖和 所需的软件包。
【讨论】:
【参考方案3】:异步我假设您实际上是指非阻塞异步 - 即,如果您有一个大(兆字节大)的 JSON 字符串,并且您进行字符串化,那么您不会'不希望您的 Web 服务器在处理对象时硬冻结和阻止新传入的 Web 请求 500 多毫秒。
选项 1
一般的答案是逐个迭代您的对象,然后在达到阈值时调用setImmedate。然后,这允许事件队列中的其他函数运行一段时间。
对于 JSON(反)序列化,yieldable-json 库做得很好。然而,它确实极大地牺牲了 JSON 处理时间(这在某种程度上是故意的)。
用法:
const yj = require('yieldable-json')
yj.stringifyAsync(key:"value", (err, data) =>
if (!err)
console.log(data)
)
选项 2
如果处理速度非常重要(例如处理实时数据),您可能需要考虑生成多个 Node 线程。我使用PM2 Process Manager 取得了巨大的成功,尽管初始设置非常艰巨。然而,一旦它起作用,最终的结果是神奇的,不需要修改你的源代码,只需要修改你的 package.json
文件。它充当 Node 应用程序的代理、负载平衡器和监控工具。它有点类似于 Docker swarm,但是是裸机,并且不需要服务器上的特殊客户端。
【讨论】:
以上是关于如何在javascript中以异步方式解析和字符串化的主要内容,如果未能解决你的问题,请参考以下文章
如何在 MongoDB 中以异步方式检索基于推送的通知的信息