首页 > 解决方案 > json stringify writeStream完成后如何解决promise?

问题描述

我正在使用 npm 的 big-json 来解决JSON.stringify()大型嵌套对象的限制。

一旦对象被字符串化,我就会将它保存到文件系统中。

然而,这整个过程减慢了我的整体处理速度——我假设这与我现在可能正在等待流超时或在它关闭之前发生的事情有关。

这是我的代码:

const fs = require('fs-extra');
const json = require('big-json');

function offlineSave(objArr){
  return new Promise((resolve, reject) => {
    let promises = [];
    for(let obj of objArr){
      const filePath = path.join(__dirname, `${obj}.json`);
      //this used to be a promisified fs.writeFile() - which seemed to be faster
      promises.push(saveStreamPromise(filePath,obj));
    }
    Promise.all(promises)
    .then((msg) =>{
      resolve(`Saved ${msg.length} files`);
    });
  });
}

let saveStreamPromise = function(filePath, obj){
  return new Promise((resolve, reject) =>{
    let stream = fs.createWriteStream(filePath, { flag: 'w+' });
    const stringifyStream = json.createStringifyStream({ body: obj});
    stringifyStream.on('data', strChunk =>{
      stream.write(strChunk);
    });

    //is this the correct way to return a promise upon stringify complete?
    stringifyStream.on('end', () =>{
      stream.end();
      resolve(`${obj} saved!`);
    });
  });
}

标签: javascriptnode.jsjsonstream

解决方案


您的代码正在侦听读取流的结束。虽然这可能有效,但最好监听写入流的结束,这样您只有在数据提交到磁盘后才解决承诺。

最好将两个流的错误处理添加到任何一个流上的任何错误都拒绝承诺:

function saveStreamPromise(filePath, obj){
  return new Promise((resolve, reject) =>{
    let stream = fs.createWriteStream(filePath, { flag: 'w+' });
    const stringifyStream = json.createStringifyStream({ body: obj});
    stringifyStream.on('data', strChunk =>{
      stream.write(strChunk);
    });

    // resolve when read stream and write stream are done
    stringifyStream.on('end', () =>{
      stream.end(function() {
          resolve('object saved!');
      });
    }).on('error', reject);
    stream.on('error', reject);
  });
}

我还建议您使用.pipe()自动将一个流馈送到另一个流,如下所示:

function saveStreamPromise(filePath, obj){
  return new Promise((resolve, reject) =>{
    let stream = fs.createWriteStream(filePath, { flag: 'w+' });
    const stringifyStream = json.createStringifyStream({ body: obj});
    stringifyStream.pipe(stream);

    // when using pipe, the write stream will automatically close when the
    // readable gets to the end of its data

    stream.on('error', reject).on('close', function() {
        resolve('object saved!');
    });
    stringifyStream.on('error', reject);
}

而且,${obj} saved!只会给你类似“[object object] 已保存!” 这不太可能是你想要的。


推荐阅读