1

I have a sequence of events that go something like this:

//Download a file and write it to disk
await downloadSyncFile(user, downloadURL)
//Use the file...
await useTheFile() //Crash! The file is only partially there! Dangit!

My code keeps moving on before the file is actually on disk. Here's my download function:

async function downloadSyncFile(user, downloadURL){
  //Setup download path
  let path = './data/'+user+'/file.whatevs'

  try{
    //Download and save file
    let stream = fs.createWriteStream(path)
    let response = await axios.get(downloadURL, { responseType: 'stream' })
    response.data.pipe(stream)

    await new Promise(fulfill => stream.on('finish', fulfill))


  }catch(error){
    console.log('downloadSyncFile Error: '+error)
    return { success: false, message: error }
  }
}

Tthe downloadSyncFile() function seems to be returning after the axios download finishes, but the write to disk isn't done.

How can I make sure the file is safely written to disk before downloadSyncFile() returns?

Clifton Labrum
  • 13,053
  • 9
  • 65
  • 128
  • You're swallowing the errors here—are you sure your `downloadSyncFile` is not returning an `{success:false,message:...}` object (return value of your catch statement)? Have you verified (eg with another event handler) that the `finish` event fires before the promise resolves? – RickN Apr 16 '20 at 08:38

1 Answers1

1

You don't return the Promise from downloadSyncFile().

Change

await new Promise(fulfill => stream.on('finish', fulfill));

to

return new Promise(fulfill => stream.on('finish', fulfill));

It would be better written like this:

async function downloadSyncFile(user, downloadURL) {
    return new Promise((fulfill, reject) => {
        let path = './data/' + user + '/file.whatevs';
        let stream = fs.createWriteStream(path);
        let response = await axios.get(downloadURL, { responseType: 'stream' });
        response.data.pipe(stream);
        stream.on('finish', fulfill));
        stream.on('error', reject); // presumably
    });
}

With everything wrapped in new Promise(...) , try{} catch() {} is unnecessary as any synchronous error will result in Promise rejection.

Roamer-1888
  • 19,138
  • 5
  • 33
  • 44