My code takes a file from S3 and copies it to my local directory. It is then supposed to read the file and print its contents to the console.
I've wrapped the section of code that copies the file in a promise and used await to ensure the file has been written before the next section attempts to read it.
When I run the below code, the file copies correctly, but the next section simply prints a blank line to the console.
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const fs = require('fs');
(async function copyAndPrintFile() {
const S3Bucket = "ExampleBucketName";
const S3File = "ExampleFileName"
// Copy file from S3 to local directory
const readParams = {
Bucket: S3Bucket,
Key: S3File,
ResponseContentType: "text/plain"
};
const copyFilePromise = new Promise((resolve, reject) =>{
const file = fs.createWriteStream(S3File);
s3.getObject(readParams).createReadStream().pipe(file);
resolve(console.log("File has been written"));
})
await copyFilePromise;
// Read contents of new file and print it to the console
let data = fs.readFileSync(S3File, 'utf-8');
console.log(data);
})();
If I run the code again without deleting the copy of the file that was created, I still receive a blank line. However, if I move the section of code that prints the file contents to the console above the promise, it will print correctly. I'm new to promises and async programming in general, and I'm struggling to figure out what I'm doing wrong.
CodePudding user response:
You are calling resolve()
BEFORE the .pipe(file)
has finished. The pipe is a non-blocking, asynchronous operation, so you're calling resolve()
when the operation has just begun, not when it's done. Instead, you need to use an event on the stream to know when it's done and call resolve()
inside that event.
For example:
const stream = s3.getObject(readParams).createReadStream().pipe(file);
stream.on('close', () => resolve(console.log("RESOLVED!")));