Node.js流-将错误转换为默认值

时间:2018-08-01 18:07:48

标签: node.js stream

我对流媒体非常陌生。假设我有一个输入流:

let inputStream = fs.createReadStream(getTrgFilePath());

我要将此输入通过管道传递到某些输出流:

inputStream.pipe(someGenericOutputStream);

就我而言,getTrgFilePath()可能不会产生有效的文件路径。这将导致失败,导致没有内容发送到someGenericOutputStream

如何设置内容,以便在inputStream遇到错误时,它会传递一些默认值(例如"Invalid filepath!")而不是失败?

示例1:

如果getTrgFilePath()无效,并且someGenericOutputStreamprocess.stdout,我想看到stdout"Invalid filepath!"

示例2:

如果getTrgFilePath()无效,并且someGenericOutputStreamfs.createOutputStream(outputFilePath)的结果,我希望在outputFilePath处找到一个内容为"Invalid filepath!"的文件。

我对不需要知道someGenericOutputStream是哪种特定流的解决方案感兴趣。

1 个答案:

答案 0 :(得分:1)

如果您只担心路径无效,则可以首先使用fs.access检查输出,但是据我了解,您不希望文件中有其他“处理”代码...

所以让我们考虑可能出问题的地方:

  1. 文件路径无效
  2. 文件或路径不存在
  3. 文件不可读
  4. 文件已读取,但失败时会发生某些事情。

现在,我将独自处理第4种情况,这是一个单独的情况,因此我们将忽略这种情况。我们需要两个文件(以便您的代码看起来干净,所有混乱都放在一个单独的文件中)-这里是./lib/create-fs-with-default.js文件:

module.exports = // or export default  if you use es6 modules
    function(filepath, def = "Could not read file") {
        // We open the file normally
        const _in = fs.createReadStream(filepath);
        // We'll need a list of targets later on
        let _piped = [];
        // Here's a handler that end's all piped outputs with the default value.
        const _handler = (e) => {
            if (!_piped.length) {
                throw e;
            }

            _piped.forEach(
                out => out.end(def)
            );
        };
        _in.once("error", _handler);

        // We keep the original `pipe` method in a variable
        const _orgPipe = _in.pipe;
        // And override it with our alternative version...
        _in.pipe = function(to, ...args) {
            const _out = _orgPipe.call(this, to, ...args);

            // ...which, apart from calling the original, also records the outputs
            _piped.push(_out);
            return _out;
        }
        // Optionally we could handle `unpipe` method here.

        // Here we remove the handler once data flow is started.
        _in.once("data", () => _in.removeListener("error", _handler));
        // And pause the stream again so that `data` listener doesn't consume the first chunk.
        _in.pause();

        // Finally we return the read stream
        return _in;
    };

现在只有一个小问题可以使用:

const createReadStreamWithDefault = require("./lib/create-fs-with-default");
const inputStream = fs.createReadStream(getTrgFilePath(), "Invalid input!");
// ... and at some point
inputStream.pipe(someOutput);

然后你去。

M。