title: Incrementing a counter asynchronously in NodeJS
body: <p>I have been struggling with this for a few hours now. What I am essentially doing is move files based on their names, in link with a SQLite database. This is in an Electron application where I use IPC. When the renderer sends a message to the main process to move files, it then listens for an answer before displaying it in the application.</p>
  
  <p>I have here very naively incremented a counter in multiple places. What I wish to do is count how many files will be moved or have been moved so that I can inform the user. The problem is that no matter what I try (Promises, async, await), the counter is never correct when it is sent. It is always 0 because the message is sent before it's incremented.</p>
  
  <p>In short, what I need to do is wait for the counter to be fully incremented before sending a message. For that, the logical thing would be to wait for dir.files() or files.forEach() to be done but I haven't been able to get any of that to work. A note: printing the counter in fs.access() right after the incrementation, the values are correct (1, 2, 3, ...), printing it outside of that asynchronous call always prints 0.</p>
  
  <p>Here is the full code:</p>
  
  <pre class="lang-js prettyprint-override"><code>ipcMain.on("moveFiles", (event, moveTo, moveFrom, databaseFile, doOverwrite, doRecursive, subFolder, doTestRun) =&gt; {
      let filesMoved = 0;
  
      const db = new sqlite3.Database(databaseFile, sqlite3.OPEN_READONLY, (cErr) =&gt; {
          if (cErr) throw cErr;
  
          let query = `...`;
  
          // Match files based on their name
          let regex = /.../;
  
          // Get data from the database in one query
          db.all(query, [], (qErr, rows) =&gt; {
              if (qErr) throw qErr;
  
              // Assume this is filled like this from the query result:
              // dbNameToFolder["imgur"] = {"type": "picture", "local_folder: "Pictures"}
              let dbNameToFolder = {};
  
              // List all files (recursively or not, based on parameter)
              dir.files(moveFrom, "file", function(error, files) {
                  if (error) throw error;
  
                  // For each file, check if it should be moved
                  files.forEach(function(file) {
                      let filename = path.basename(file);
  
                      // Run the filename against the regex
                      let matches = regex.exec(filename);
  
                      // If the filename matched
                      if (matches !== null &amp;&amp; matches.length &gt; 1 &amp;&amp; dbNameToFolder.hasOwnProperty(matches[2])) {
                          let newPath = path.join(moveTo, dbNameToFolder[matches[2]]["type"], dbNameToFolder[matches[2]]["local_folder"], subFolder, filename);
  
                          // If this a test run, simply inform the user of which files will be moved
                          if (doTestRun) {
                              // If the user didn't ask for files to be overwritten
                              if (!doOverwrite) {
                                  // Check if there already is a file at the newly defined path
                                  fs.access(newPath, fs.F_OK, (aErr) =&gt; {
                                      // If aErr, target file doesn't exist, we can move it freely
                                      if (aErr) {
                                          console.log("Will move ", file, " to ", newPath);
                                          filesMoved++;
                                      } else {
                                          console.log("Moving ", file, " would overwrite ", newPath);
                                      }
                                  });
                              } else {
                                  console.log("Will move ", file, " to ", newPath);
                                  filesMoved++;
                              }
                          } else {
                              // Move files asynchronously
                              (async () =&gt; {
                                  await moveFile(file, newPath, {
                                      overwrite: doOverwrite
                                  });
                                  console.log(file, " has been moved to ", newPath);
                                  filesMoved++;
                              })();
                          }
                      }
                  });
              }, {
                  recursive: doRecursive
              });
          });
      });
  
      db.close();
  
      mainWindow.webContents.send("moveFilesResult", filesMoved);
  });
  </code></pre>
  
  <p>And here is an attempt I made.</p>
  
  <pre class="lang-js prettyprint-override"><code>ipcMain.on("moveFiles", (event, moveTo, moveFrom, databaseFile, doOverwrite, doRecursive, subFolder, doTestRun) =&gt; {
      const db = new sqlite3.Database(databaseFile, sqlite3.OPEN_READONLY, (cErr) =&gt; {
          db.all(query, [], async (qErr, rows) =&gt; {
              const run = () =&gt; {
                  return new Promise(resolve =&gt; {
                      let filesMoved = 0;
  
                      dir.files(moveFrom, "file", function (error, files) {
                          files.forEach(function (file) {
                              let filename = path.basename(file);
                              let matches = regex.exec(filename);
  
                              if (matches !== null &amp;&amp; matches.length &gt; 1 &amp;&amp; dbNameToFolder.hasOwnProperty(matches[2])) {
                                  let newPath = path.join(moveTo, dbNameToFolder[matches[2]]["type"], dbNameToFolder[matches[2]]["local_folder"], subFolder, filename);
  
                                  if (doTestRun) {
                                      if (!doOverwrite) {
                                          fs.access(newPath, fs.F_OK, (aErr) =&gt; {
                                              if (aErr) {
                                                  console.log("Will move ", file, " to ", newPath);
                                                  filesMoved++;
                                              } else {
                                                  console.log("Moving ", file, " would overwrite ", newPath);
                                              }
                                          });
                                      } else {
                                          console.log("Will move ", file, " to ", newPath);
                                          filesMoved++;
                                      }
                                  } else {
                                      (async () =&gt; {
                                          await moveFile(file, newPath, {
                                              overwrite: doOverwrite
                                          });
                                          console.log(file, " has been moved to ", newPath);
                                          filesMoved++;
                                      })();
                                  }
                              }
                          });
                      }, {
                          recursive: doRecursive
                      });
  
                      resolve(filesMoved);
                  });
              };
  
              let filesMoved = await run();
              console.log(filesMoved);
              mainWindow.webContents.send("moveFilesResult", filesMoved);
          });
      });
  
      db.close();
  });
  </code></pre>
  
  <p>So the goal here is to wait for all operations on files to be done before sending back a message containing any data relating to what was just done (a counter or the list of files, for example). Are race conditions a thing in NodeJS? How would I go about doing this the right way?</p>