如何在 Node 中使用 aws-sdk 处理 NoSuchKey 错误

How to handle a NoSuchKey error with aws-sdk in Node

我不明白为什么我的错误处理没有捕获来自 S3 的 'NoSuchKey' 错误。

都在一个try/catch里,回调里也有错误处理。

我错过了什么?

const s3 = new AWS.S3({ endpoint: new AWS.Endpoint(...) });
const Key = '/this/file/doesnt/exist';
const dropboxConnection = ...

const streamFromS3 = (Key) => {
    return new Promise((resolve, reject) => {
        try {
            const fileStream = s3.getObject({ Bucket: 'mybucket', Key }).createReadStream();
            const dropboxUploadStream = dropboxConnection(
                {
                    resource: 'files/upload',
                    parameters: {
                        path: destination,
                    },
                },
                (err, result, response) => {
                    if (err) {
                        reject(err);
                        return;
                    }
                    resolve({ result, response });
                }
            );

            // This then crashes the whole app, with
            // "NoSuchKey: The specified key does not exist."
            // regardless of the try/catch it's nested in

            fileStream.pipe(dropboxUploadStream);
        } catch (e) {
            reject(e);
        }
    });
};

无论何时使用流,都需要添加错误处理程序。例如

const fileStream = s3.getObject({ Bucket: 'mybucket', Key }).createReadStream();

fileStream.on('error', (err) => reject(err));

当您进行管道传输时,您通常还需要一个处理管道结果的处理程序:

  fileStream.pipe(dropboxUploadStream)
    .on('error', (err) => reject(err));

而不是直接使用 pipe,您可以使用 pipeline,它本质上将一系列管道流组合在一起,因此您只需要一个错误处理程序(即,您可以省略 on('error' 以上)。

pipeline(fileStream, dropboxUploadStream, (err) => {
  if (err) {
    reject(err);
  } else {
    resolve();
  }
});

最后,如果您使用的是节点 14+,管道本身将 return 一个没有回调的承诺。因为无论如何你只想把所有的错误都冒出来,所以很确定你可以把整个事情减少到下面(但一定要在调用者中捕获错误):

const streamFromS3 = async (Key) => {
  const readStream = s3.getObject({ Bucket: 'mybucket', Key }).createReadStream();

  const writeStream = dropboxConnection({
    resource: 'files/upload',
    parameters: {
      path: 'sdfsdf',
    },
  });

  await pipeline(readStream, writeStream);
};

以下是有关管道的更多信息: https://dev.to/morz/pipeline-api-the-best-way-to-handle-stream-errors-that-nobody-tells-you-about-122o