读取本地文件流并回退到其他源

时间:2016-04-15 10:57:25

标签: node.js stream promise fs

我将文件存储在Amazon S3中,但也维护本地文件缓存。当我需要一个文件时,我想先检查一下缓存。我想避免在读取之前测试本地文件存在,因为fs.exists将被弃用,并且文件实际上可以在exists-check和文件读取之间删除。

我想使用promises和stream。下面的示例有一个回退到另一个本地文件。我的真实代码将S3作为后备。

以下是一个好的解决方案吗? 我发现获取失败读取信息的唯一方法是将错误处理程序连接到流。一旦我得到"可读"事件我取消了我的临时错误处理程序。

我也想知道当我使用"一次"我真的需要解开处理程序。把它搞定。

'use strict';
const fs = require('fs');

function tryToReadLocalFile() {
  return new Promise(function(resolve, reject) {
    let rs = fs.createReadStream('./test1.txt');

    let errorListener = function(err) {
      reject(err);
    };

    rs.once('error', errorListener)

    rs.on('readable', () => {
      rs.removeListener('error', errorListener);
      resolve(rs)
    });
  });    
}

function tryToReadAnotherFile() {
  return new Promise(function(resolve, reject) {
    let rs = fs.createReadStream('./test2.txt');

    let errorListener = function(err) {
      reject(err);
    };

    rs.once('error', errorListener)

    rs.on('readable', () => {
      rs.removeListener('error', errorListener);
      resolve(rs)
    });    
  });
}

tryToReadLocalFile()
.catch(function(err) {
  if(err.code === 'ENOENT') {
    console.log('test1.txt not found. Fallback to test2.txt')

    //Reading from another file as a test. Should read from S3 as fallback
    return tryToReadAnotherFile();
  } else {
    return Promise.reject(err);
  }
}).then(function(file) {
  console.log('writing to test.txt');
  let ws = fs.createWriteStream('./test.txt');
  file.pipe(ws);
});

---------- edit - >

我现在已经实现了上述更紧凑的版本。不过,我仍然会对此提出任何意见表示感谢。这是解决这个问题的好方法吗?

如你所见,我不再费心去检查ENOENT了。无论错误是什么,我都想回到S3。

function getFileFromStorageP(options) {
  return new Promise(function(resolve, reject) {
    let rs = fs.createReadStream(path.join(env.fsp.cacheDir, options.fileId));
    rs.once('error', (err) => {reject(err)});
    rs.once('readable', () => {resolve(rs)});
  }).catch(function(err) {
    return srvS3.download({
      fileId: options.fileId
    });
  });
}

1 个答案:

答案 0 :(得分:0)

我会给别人发一个答案来阅读..

上述解决方案现已实施,效果很好。但是,我还没有找到更容易解决错误的方法。