0

Here is the code in question:

        const scriptFiles = fs.readdirSync(scriptsPath)
            .filter(file => file.endsWith(".sql"));

        for (const file of scriptFiles) {

            var data = fs.readFileSync(`${scriptsPath}/${file}`, 'utf8');
            fs.appendFile(`${scriptsPath}/Hotfix.sql`, data.toString() + "\n", (err) => {
                if (err) throw new Error(err)
                console.log('Appending ' + file + '...')
            })

            process.stdout.cursorTo(0);
        }

        console.log(`start ${scriptsPath}/Hotfix.sql`)
        exec(`start ${scriptsPath}/Hotfix.sql`)

The problem that I'm running into is that it is attempting to open/start scriptsPath/Hotfix.sql before anything has been appended to the file. For example, here is the output from the console.log()s I've added to the script:

start scriptsPath/Hotfix.sql
Appending file1.sql...    
Appending file2.sql...

is there a way I can have the script wait until the for loop has completed before attempting to execute the command?

Revircs
  • 1,312
  • 3
  • 12
  • 23
  • 1
    You're already using the `*Sync` versions so why did you then switch to the async `.appendFile()` instead of sticking with `.appendFileSync()`? – Andreas Oct 27 '20 at 16:35
  • The (imho) better way would be to understand how asynchronous code/functions work and how to work with them. This would then also hopefully lead to the conclusion that it should be `console.log('File ' + file + ' has been appended')` and not `'Appending...'` (and at which place of your script you can safely work with the appended file) – Andreas Oct 27 '20 at 16:38
  • @Andreas It's been a year or two since I've had the opportunity to work with Node and I completely forgot that appendFileSync() existed. Thanks for the heads up! – Revircs Oct 29 '20 at 15:10

2 Answers2

1

Either use .appendFileSync() and remove the (err)=> callback, or write your code as async entirely.

There is an async version of the fs API, you can access it via require('fs').promises.

In that case, you will have to use await, your code must be an async function. For an utility script that only does one thing, the benefit of doing it that way is questionable.

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
1

Replace the appendFile() asynchronous method with the appendFileSync() synchronous method so that code waits until the loop has completed.

const scriptFiles = fs.readdirSync(scriptsPath)
  .filter(file => file.endsWith(".sql"));

for (const file of scriptFiles) {

  var data = fs.readFileSync(`${scriptsPath}/${file}`, 'utf8');
  fs.appendFileSync(`${scriptsPath}/Hotfix.sql`, data.toString() + "\n");

  process.stdout.cursorTo(0);
}

console.log(`start ${scriptsPath}/Hotfix.sql`)
exec(`start ${scriptsPath}/Hotfix.sql`)
Lahiru Tennakoon
  • 621
  • 1
  • 6
  • 8