Alfagun74
Alfagun74

Reputation: 3

Node.js "fs.writeFile()" callback inside of Promise.all executes after Promise.all has resolved

I am trying to log something after a bunch of files have been written using Promise.all. But somehow the last file in my array always calls back after the Promise.all has resolved.

Please see the code & output below.

Promise.all(videos.map(async (video) => {
            const dest = `${destinationFolder}/${video.name}`;
            const response = await fetch(video.url);
            const buffer = await response.buffer();
            await fs.writeFile(dest, buffer, () => {
                console.log(`✔ Downloaded video: ${video.name} to ${dest}`);
            });
        }
    )).then(() => {
        console.log(`✨ Downloaded all videos to ${destinationFolder}`);
    });

Expected output:

✔ Downloaded video: video1.mp4 to ./dest/video1.mp4
✔ Downloaded video: video2.mp4 to ./dest/video2.mp4
✨ Downloaded all videos to ./dest

Actual output:

✔ Downloaded video: video1.mp4 to ./dest/video1.mp4
✨ Downloaded all videos to ./dest
✔ Downloaded video: video2.mp4 to ./dest/video2.mp4

Upvotes: 0

Views: 2311

Answers (2)

z1ne2wo
z1ne2wo

Reputation: 278

To use await, you need a version of the function that returns a Promise, this version is in the promises namespace:

Promise.all(videos.map(async (video) => {
    const response = await fetch(video.url);
    const destination = `${folder}/${video.name}`;
    await fs.promises.writeFile(destination, await response.buffer());

    console.log(`✔ Downloaded video: ${video.name} to ${destination}`);
)).then(() => {
    console.log(`✨ Downloaded all videos to ${folder}`);
});

Upvotes: 1

Anatoly
Anatoly

Reputation: 22803

fs.writeFile uses callback to return a result and it doesn't return Promise. You can use new Promise to convert this call with a callback into async call.

const writeFilePromise = new Promise((resolve, reject) => {
  fs.writeFile(dest, buffer, (err) => {
                if (err) {
                  reject(err)
                }
                console.log(`✔ Downloaded video: ${video.name} to ${dest}`);
                resolve()
            });
});
await writeFilePromise;

Upvotes: 0

Related Questions