簡體   English   中英

如何正確清除節點中可讀流的內部緩沖區?

[英]How to properly clear the internal buffer of a readable stream in node?

我正在處理我的自定義轉換流。 由於我手動處理緩沖和緩存,因此我需要確保在重新管道時不會自動發送任何塊。 為此,我應該在嘗試調用.pipe()

由於我的流邏輯非常復雜,我制作了這個簡化的示例來幫助您更好地理解我要解決的問題:

const { Readable, Writable } = require('stream')
const wait = ms => new Promise(res => setTimeout(res, ms))

;(async () => {
    const readable = new Readable()
    readable._read = () => {}

    const writable = new Writable()
    writable._write = (chunk, _encoding, callback) => {
        console.log(chunk.toString())
        callback()
    }

    readable.pipe(writable)
    await wait(100) // This small delay replaces listening to the pipe/unpipe events 

    readable.push('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')

    console.log('unpipe')
    readable.unpipe(writable)
    await wait(100)

    readable.push('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb')

    // readable.clearInternalBufferOrWhatever() // ???

    console.log('pipe')
    readable.pipe(writable)
    await wait(100)

    readable.push('ccccccccccccccccccccccccccccccc')
})()

// => aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa (Expected ✔)
//    unpipe
//    pipe
//    bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb (Unexpected ❌)
//    ccccccccccccccccccccccccccccccc (Expected ✔)

如您所見,可寫流已成功接收到第二個塊( 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ),這就是我要避免的。 有任何想法嗎?

我想到了! 流有一個名為_readableState的內部屬性,其中包含內部緩沖區。 只需兩行代碼即可清除它:

readable._readableState.buffer.clear()
readable._readableState.length = 0

請注意, _readableState並不安全,因為它是內部的且未記錄在案,並且隨時可能發生重大更改。 但是,已確認此解決方案適用於節點 v8.10.0 和 v14.17.2。

這是一個完整的工作示例:

const { Readable, Writable } = require('stream')
const wait = ms => new Promise(res => setTimeout(res, ms))

;(async () => {
    const readable = new Readable()
    readable._read = () => {}

    const writable = new Writable()
    writable._write = (chunk, _encoding, callback) => {
        console.log(chunk.toString())
        callback()
    }

    readable.pipe(writable)
    await wait(100)
    readable.push('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')

    console.log('unpipe')
    readable.unpipe(writable)
    await wait(100)

    readable.push('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb')

    readable._readableState.buffer.clear()
    readable._readableState.length = 0

    console.log('pipe')
    readable.pipe(writable)
    await wait(100)

    readable.push('ccccccccccccccccccccccccccccccc')
})()

// => aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
//    unpipe
//    pipe
//    ccccccccccccccccccccccccccccccc

來自 Node 在readable.read()上的流文檔

如果沒有數據可供讀取,則返回null

因此,如果我們一直調用readable.read()直到返回null ,那么內部緩沖區應該被清空。

function clearReadBuffer(readable) {
  while (true) {
    const chunk = readable.read();
    if ( chunk === null ) return;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM