【问题标题】:Node.js: splitting stream content for n-partsNode.js:为 n 部分拆分流内容
【发布时间】:2017-09-23 16:29:00
【问题描述】:

我正在尝试了解节点流及其生命周期。所以,我想将流的内容拆分为 n 部分。下面的代码只是为了解释我的意图并表明我已经自己尝试了一些东西。我省略了一些细节

我有一个流,它只生成一些数据(只是一个数字序列):

class Stream extends Readable {
  constructor() {
    super({objectMode: true, highWaterMark: 1})
    this.counter = 0
  }

  _read(size) {
    if(this.counter === 30) {
      this.push(null)
    } else {
      this.push(this.counter)
    }
    this.counter += 1
  }
}

const stream = new Stream()
stream.pause();

一个试图获取n个下一个块的函数:

function take(stream, count) {
  const result = []
  return new Promise(function(resolve) {
    stream.once('readable', function() {
      var chunk;
      do {
        chunk = stream.read()
        if (_.isNull(chunk) || result.length > count) {
          stream.pause()
          break
        }
        result.push(chunk)
      } while(true)
      resolve(result)
    })
  })
}

并想像这样使用它:

take(stream, 3)
  .then(res => {
    assert.deepEqual(res, [1, 2, 3])
    return take(stream, 3)
  })
  .then(res => {
    assert.deepEqual(res, [4, 5, 6])
  })

这样做的惯用方法是什么?

【问题讨论】:

    标签: javascript node.js node.js-stream


    【解决方案1】:

    我认为这可以帮助你 - https://github.com/substack/stream-handbook

    这是一本非常详细的手册,其中包含适用于各种流媒体场景的示例代码,我将其用作我自己项目的参考,并且到目前为止发现它很有用!它在/examples 中也有示例代码

    【讨论】:

    【解决方案2】:

    使用ReadableStream,您可以使用单个函数来检查当前数据块的元素是否等于预期结果。

    创建变量,CHUNKN,其中 CHUNK 是要从原始数组切片或拼接的元素数,N 是在 @ 内每次调用 .enqueue() 时增加 CHUNK 的变量987654331@电话。

    const [data, CHUNK, result] = [[1,2,3,4,5,6], 3, []];
    
    let N = 0;
    
    const stream = new ReadableStream({
      pull(controller) {
        if (N < data.length)
          // slice `N, N += CHUNK` elements from `data`
          controller.enqueue(data.slice(N, N += CHUNK))
        else
          // if `N` is equal to `data.length` call `.close()` on stream
          controller.close()
      }
    });
    
    const reader = stream.getReader();
    
    const processData = ({value, done}) => {
      // if stream is closed return `result`; `reader.closed` returns a `Promise`
      if (done) return reader.closed.then(() => result);
      if (data.slice(N - CHUNK, N).every((n, index) => n === value[index])) {
        console.log(`N: ${N}, value: [${value}]`)
        result.push(...value);
        return reader.read().then(data => processData(data))
      }
    }
    
    const readComplete = res => console.log(`result: [${res}]`);
    
    reader.read()
    .then(processData)
    .then(readComplete)
    .catch(err => console.log(err));

    使用链式.then()

    const [data, CHUNK, result] = [[1,2,3,4,5,6], 3, []];
    
    let N = 0;
    
    const stream = new ReadableStream({
      pull(controller) {
        if (N < data.length)
          // slice `N, N += CHUNK` elements from `data`
          controller.enqueue(data.slice(N, N += CHUNK))
        else
          // if `N` is equal to `data.length` call `.close()` on stream
          controller.close()
      }
    });
    
    const reader = stream.getReader();
    
    const processData = ({value, done}) => {
      // if stream is closed return `result`; `reader.closed` returns a `Promise`
      if (done) return reader.closed.then(() => result);
      if (data.slice(N - CHUNK, N).every((n, index) => n === value[index])) {
        console.log(`N: ${N}, value: [${value}]`)
        result.push(...value);
        return reader.read().then(data => processData(data))
      }
    }
    
    const readComplete = res => console.log(`result: [${res}]`);
    
    reader.read()
    .then(({value, done}) => {
      if ([1,2,3].every((n, index) => n === value[index])) {
        console.log(`N: ${N}, value: [${value}]`)
        result.push(...value);
        return reader.read()
      }
    })
    .then(({value, done}) => {
      if ([4,5,6].every((n, index) => n === value[index])) {
        console.log(`N: ${N}, value: [${value}]`)
        result.push(...value);
        // return `result`; `reader.closed` returns a `Promise`
        return reader.closed.then(() => result);
      }
    })
    .then(readComplete)
    .catch(err => console.log(err));

    另见Chrome memory issue - File API + AngularJS

    【讨论】:

    • 您能否提供一些有关 ReadableStream 的文档的链接?实际的问题是关于 Node.js 流的,这可能是不同的
    • 这不是预期的答案,但我可能会给你奖励。至少我在里面发现了一些新东西
    • @kharandziuk 不确定nodejs 是否实现了 Streams Standard,尽管这是规范。如果该标准由nodejs 实施,您可以询问标准的维护者之一或nodejs 维护者。
    猜你喜欢
    • 2016-09-17
    • 2017-08-06
    • 2011-03-12
    • 2013-09-29
    • 1970-01-01
    • 1970-01-01
    • 2020-05-23
    • 2012-04-27
    • 1970-01-01
    相关资源
    最近更新 更多