简体   繁体   中英

How to await Function to finish before executing the next one?

// The Below code already contains the suggestions from the answers and hence works :)

within the below script I tried to fully execute the 'createDatabase' function before the .then call at the end starts to run. Unfortunately I couldn't figure out a solution to achieve just that.

In generell the flow should be as followed:

  1. GetFiles - Fully Execute it
  2. CreateDatabase - Fully Execute it (while awaiting each .map call to finish before starting the next)
  3. Exit the script within the .then call

Thanks a lot for any advise :)

const db = require("../database")
const fsp = require("fs").promises
const root = "./database/migrations/"

const getFiles = async () => {
  let fileNames = await fsp.readdir(root)
  return fileNames.map(fileName => Number(fileName.split(".")[0]))
}

const createDatabase = async fileNumbers => {
  fileNumbers.sort((a, b) => a - b)
  for (let fileNumber of fileNumbers) {
    const length = fileNumber.toString().length
    const x = require(`.${root}${fileNumber.toString()}.js`)
    await x.create()
  }
}

const run = async () => {
  let fileNumbers = await getFiles()
  await createDatabase(fileNumbers)
}

run()
  .then(() => {
    console.log("Database setup successfully!")
    db.end()
    process.exitCode = 0
  })
  .catch(err => {
    console.log("Error creating Database!", err)
  })

The x.create code looks as follows:

const dbQ = (query, message) => {
  return new Promise((resolve, reject) => {
    db.query(query, (err, result) => {
      if (err) {
        console.log(`Error: ${err.sqlMessage}`)
        return reject()
      }
      console.log(`Success: ${message}!`)
      return resolve()
    })
  })
}

x.create = async () => {
  const query = `
    CREATE TABLE IF NOT EXISTS Country (
      Code CHAR(2) UNIQUE NOT NULL,
      Flag VARCHAR(1024),
      Name_de VARCHAR(64) NOT NULL,
      Name_en VARCHAR(64) NOT NULL,

      Primary Key (Code)
    )`

  const result = await dbQ(query, "Created Table COUNTRY")
  return result
}

If you want each x.create to fully execute before the next one starts, ie this is what I interpret where you say while awaiting each .map call to finish before starting the next - then you could use async/await with a for loop as follows:

const createDatabase = async fileNumbers => {
  fileNumbers.sort((a, b) => a - b);
  for (let fileNumber of fileNumbers) {
    const x = require(`.${root}${fileNumber.toString()}.js`);
    await x.create();
  })
}

However, this also assumes that x.create() returns a Promise - as you've not shown what is the typical content of .${root}${fileNumber.toString()}.js file is, then I'm only speculating

The other interpretation of your question would simply require you to change createDatabase so that promises is actually an array of promises (at the moment, it's an array of undefined

const createDatabase = async fileNumbers => {
  fileNumbers.sort((a, b) => a - b);
  const promises = fileNumbers.map(fileNumber => {
    const x = require(`.${root}${fileNumber.toString()}.js`);
    return x.create();
  })
  await Promise.all(promises);
}

Now all .create() run in "parallel", but createDatabase only resolves onces all promises returned by x.create() resolve - again, assumes that x.create() returns a promise

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM