说说Node.js的流模块Stream之Stream模块的可写流类:stream. Writable

 2015年11月18日    464     声明


可写流(Writable stream)接口是对正在写入数据目标的抽象,也可以认为,数据要写入一个 Writable流。可写流中有些事件是由可读流触发的,如:当可读流将数据导向可写流时,会触发可写流中的'pipe'事件。

  1. 可写流中的事件
  2. 可写流中的方法


1. 可写流中的事件

事件:'drain'

当存在可写入数据,即:writable.write(chunk)方法返回false,且数据可继续写入时会触发'drain'事件。


事件:'finish'

当调用writable.end()方法且所有数据已被写入底层系统后,'finish'事件会被触发。


事件:'pipe'

当可读流导流到本可写流时,即:调用pipe()方法时,会触发'pipe'事件。

事件的回调函数中有一个参数src,表示可读流导流到本可写流的来源流。

var writer = getWritableStreamSomehow();
var reader = getReadableStreamSomehow();
writer.on('pipe', function(src) {
  console.error('数据正在被导流到 writer');
  assert.equal(src, reader);
});
reader.pipe(writer);


事件:'unpipe'

当可读流移除导流到本可写流时,即:调用unpipe()方法时,会触发'unpipe'事件。

var writer = getWritableStreamSomehow();
var reader = getReadableStreamSomehow();
writer.on('unpipe', function(src) {
  console.error('可读流停止导流到 writer 了');
  assert.equal(src, reader);
});
reader.pipe(writer);
reader.unpipe(writer);


事件:'error'

向可写流写入数据或导流发生错误时,会触发'error'事件。其回调函数中有一个参数{Error Object},表示错误信息。


2. 可写流中的方法

向可写流写入数据:writable.write()

writable.write(chunk, [encoding], [callback])
  • chunk {String | Buffer},表示要写入的数据
  • encoding {String} 编码,当写入的 chunk 是一个字符串时,可以设置编码
  • callback {Function} 数据块写入后的回调
  • 返回: {Boolean} 如果数据已被全部处理则返回 true

write()方法用于向底层系统写入数据,在数据被处理完毕后会调用所指定的回调函数

返回值表示是否有继续写入的数据,如果仍有未写入的数据,会返回 false;否则返回 true

返回值所表示的状态仅供参考,因为数据有可能滞留在内存中,而应该在'drain'事件触发后继续写入数据。

// 向可写流写入 1000000 次数据。
// 注意后端压力。
function writeOneMillionTimes(writer, data, encoding, callback) {
  var i = 1000000;
  write();
  function write() {
    var ok = true;
    do {
      i -= 1;
      if (i === 0) {
        // 最后一次!
        writer.write(data, encoding, callback);
      } else {
        // 检查是应该继续还是等待
        // 不要传递回调函数,因为还没有完成。
        ok = writer.write(data, encoding);
      }
    } while (i > 0 && ok);
    if (i > 0) {
      // 不得不提前停止!
      // 排空后,继续数据写入
      writer.once('drain', write);
    }
  }
}


缓存要写入的数据:writable.cork()

writable.cork()

cork()方法会强行滞留要写入的数据。被滞留的数据可以在调用uncork()end()方法时写入。


写入被滞留的数据:writable.uncork()

writable.uncork()

uncork()方法用于写入所有被cork()方法滞留的数据。


结束数据写入:writable.end()

writable.end([chunk], [encoding], [callback])
  • chunk {String | Buffer} 可选,表示最后要写入的数据
  • encoding {String} 编码,当写入的 chunk 是一个字符串时,可以设置编码
  • callback {Function} 可选,流结束写入后的回调

cork()方法会强行滞留要写入的数据。被滞留的数据可以在调用uncork()end()方法时写入。

当没有更多数据可写入到可写流时调用此方法,调用后'finish'事件会被触发。

注意:调用end()方法结束写入后,再次调用write()方法会报错。

// 写入 'hello, ' 然后以 'world!' 结束
http.createServer(function (req, res) {
  res.write('hello, ');
  res.end('world!');
  // 现在不允许继续写入了
});