node.js实现自己的Writable

自定义 writable 实现下载文件为 buffer

writable 是 node.js strem api 中的一个概念, 让我们可以以流(stream)的方式操作数据.更多信息可以参考官方文档

通过 node.js 的http module 可以实现文件下载. 但 http.get 方法返回的结果类型是 stream. 你需要先保存 stream 到文件中, 等待下载结束后再次读取文件获得图片内容. 但有时不方便保存图片到 fs, 你需要直接获得图片的buffer.

继承Writable, 实现 _write 方法

const util = require('util');
const {Writable} = require('stream');

// --------------------------
// CacheWritable
// --------------------------
/**
 * 接受下载结果, 缓冲合并为一个buffer后返回
 * @extends {NodeJS.WritableStream}
 * @param options
 * @constructor
 */
function CacheWritable(options) {
  this._chunks = [];
  Writable.call(this, options);
}

util.inherits(CacheWritable, Writable)
CacheWritable.prototype._write = function (chunk, encoding, cb) {
  this._chunks.push(chunk);
  cb && cb();
};
CacheWritable.prototype.getBuffer = function () {
  let res = Buffer.concat(this._chunks);
  this._chunks.splice(0, this._chunks.length);
  return res;
};

_write 方法是唯一需要实现的方法. 注意 write 方法的参数 cb 一定要调用, 否则steam会认为_write方法没有完成, 导致 stream 卡住.

把 http.get 封装为Promise

const http = require('http');
const https = require('https');

/**
 * 下载
 * @param {string} url
 * @return {Promise<Buffer>}
 */
async function download(url) {
  let act = http;
  if (url.indexOf('https://') === 0) {
    act = https;
  }
  return new Promise((resolve, reject) => {
    act.get(url, (result) => {
      let write = new CacheWritable({emitClose: true});
      write.on('finish', () => {
        resolve(write.getBuffer());
      });
      result.pipe(write);
    }).on('error', reject);
  });
};

这里需要注意

  1. 需要监听 on(‘finish’) 事件并且返回结果. 因为 close 事件在流关闭时才发出. 如果数据传递完毕了, 但 stream 继续 keepAlive, 那么短时间内你都不会受到 close 方法
  2. 你不能通过覆盖 writable.end 方法来处理 finish, close 等事件. 阅读node.js 的代码后, 你就会发现 writable.end 已经实现了, 你幷不能通过修改 end 方法来实现自己的事件处理逻辑. 他们只能通过监听 EventEmitter 实现.

其他实现方法

你可以通过 request, concat-stream 这两个模块实现上面的功能.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wlpsjgs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值