如何在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 中以异步方式检索基于推送的通知的信息

如何在 Pyspark 中以编程方式解析固定宽度的文本文件?

如何在 Spring 中以编程方式解析属性占位符

在 C# 中以编程方式编译打字稿?

javascript脚本异步加载的几种方式

以编程方式获取 Android 手机型号,如何在 android 中以编程方式获取设备名称和型号?