0

I have a code that helps me rename multiple files with a data. In the data (rarityList) there is a name and a value for each file I have. For the sake of the post I just replaced the values with a dummy but you can imagine there is 500 of them.

It works and does the job but in a way that I did not intend. In the terminal it first prints 0(total) then copies all files and then renames it. But I was expecting to see something like Copying is done! and Renaming is done! and finally total number at the end of the terminal. Could you explain to me what I am missing here?

const fs = require("fs");
const path = "C:\\Users\\shepard\\Desktop\\Head";
const newPath = "C:\\Users\\shepard\\Desktop\\NewHead";
let files = fs.readdirSync(path);
const rarityList = [{name: "a", value: 3},{name: "b", value: 2}];
let total = 0;

const copy = async (_e) => {
    fs.copyFile(path + "\\" + _e, newPath + "\\" + _e, err => {if (err) {console.log(err)}});
  };

const rename = async (_e, _index) => {
    let t = _e.replace(".png", "#" + rarityList[_index].value + ".png")
    fs.rename(newPath + "\\" + _e, newPath + "\\" + t, err => {if (err) {console.log(err)}});
  };

files.forEach(async (e) => {
    await copy(e);
    console.log("Copying is done!");

    rarityList.forEach(async (element, index) => {
      if (element.name == e.slice(0,-4)) {
          await rename(e,index);
          console.log("Renaming is done! for " + e + " with the rarity weight of " + rarityList[index].value);
          total += rarityList[index].value;
      };
    });
});

console.log(total);
  • 2
    You are using [callback](https://nodejs.org/api/fs.html#fs_fs_rename_oldpath_newpath_callback) versions of the node functions and just wrapping them in a function marked as `async` won't do anything to wait for that to finish. Also, `Array.prototype.forEach` will *never* wait for an `async` function to finish. – crashmstr Sep 24 '21 at 21:20
  • You can check a [possible answer](https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop) here, using the `for` method – roneicostajr Sep 24 '21 at 21:20
  • `forEach(async …` is a common mistake – use `for (const e of files)` instead. – Ry- Sep 24 '21 at 21:22
  • Does this answer your question? [How do I convert an existing callback API to promises?](https://stackoverflow.com/questions/22519784/how-do-i-convert-an-existing-callback-api-to-promises) – Ivar Sep 24 '21 at 21:32

1 Answers1

0

Possibly not the best answer, but a solution:

const fs = require("fs");
const path = "C:\\Users\\shepard\\Desktop\\Head";
const newPath = "C:\\Users\\shepard\\Desktop\\NewHead";
let files = fs.readdirSync(path);
const rarityList = [
  { name: "a", value: 3 },
  { name: "b", value: 2 },
];
let total = 0;

const copy = async (_e) => {
  fs.copyFile(path + "\\" + _e, newPath + "\\" + _e, (err) => {
    if (err) {
      console.log(err);
    }
  });
};

const rename = async (_e, _index) => {
  let t = _e.replace(".png", "#" + rarityList[_index].value + ".png");
  fs.rename(newPath + "\\" + _e, newPath + "\\" + t, (err) => {
    if (err) {
      console.log(err);
    }
  });
};

const renameFiles = async () => {
  for (let e of files) {
    await copy(e);
    let index = 0;
    for (let element of rarityList) {
      if (element.name == e.slice(0, -4)) {
        await rename(e, index);
        console.log(
          "Renaming is done! for " +
            e +
            " with the rarity weight of " +
            rarityList[index].value
        );
        total += rarityList[index].value;
      }
      index += 1;
    }
  }
  console.log('in async func', total);
};

renameFiles();
console.log('out of async function', total);

The trick is that the async function is not waited for, so total isn't updated at the "top level". You can do a "top level" await like this:

const fs = require("fs");
const path = "C:\\Users\\shepard\\Desktop\\Head";
const newPath = "C:\\Users\\shepard\\Desktop\\NewHead";
let files = fs.readdirSync(path);
const rarityList = [
  { name: "a", value: 3 },
  { name: "b", value: 2 },
];
let total = 0;

const copy = async (_e) => {
  fs.copyFile(path + "\\" + _e, newPath + "\\" + _e, (err) => {
    if (err) {
      console.log(err);
    }
  });
};

const rename = async (_e, _index) => {
  let t = _e.replace(".png", "#" + rarityList[_index].value + ".png");
  fs.rename(newPath + "\\" + _e, newPath + "\\" + t, (err) => {
    if (err) {
      console.log(err);
    }
  });
};

const renameFiles = async () => {
  for (let e of files) {
    await copy(e);
    let index = 0;
    for (let element of rarityList) {
      if (element.name == e.slice(0, -4)) {
        await rename(e, index);
        console.log(
          "Renaming is done! for " +
            e +
            " with the rarity weight of " +
            rarityList[index].value
        );
        total += rarityList[index].value;
      }
      index += 1;
    }
  }
  console.log("in function", total);
};

(async function() {
  await renameFiles()
  console.log(total)
}());
ᴓᴓᴓ
  • 1,178
  • 1
  • 7
  • 18