12

Cannot seem to figure out why this is not working for me. I have a parent function that performs an AWAIT on a child load process... the LOAD process in turn calls another AWAIT called LOADDATA... so basically like this:

module.exports = async function () {
    try {
       await load();

    } catch (ex) {
        console.log(ex);
        logger.error(ex);
    }
};

async function load() {
    return await new Promise((resolve, reject) => {
        TableImport.findAll().then((tables) => {
           for (let table of tables) {
                await loadData(table.fileName, table.tableName);
            }
            resolve();
        }).catch(function (err) {
            reject(err);
        })
    })
};


async function loadData(location, tableName) {
    return await new Promise(function (resolve, reject) {
        var currentFile = path.resolve(__dirname + '/../fdb/' + location);

        sequelize.query("LOAD DATA LOCAL INFILE '" + currentFile.replace('/', '//').replace(/\\/g, '\\\\') + "' INTO TABLE " + tableName + " FIELDS TERMINATED BY '|'").then(function () {
            resolve(tableName);
        }).catch(function (ex) {
            reject();
        });
    });
};

the AWAIT in the LOAD fails stating:

await loadData(table.fileName, table.tableName); SyntaxError: Unexpected identifier

Clearly do not understand something about scope of the async!

1
  • There is no reason to do return await .... Just return the promise. Also, should avoid the promise anti-pattern of wrapping a new promise around existing promises. Commented Dec 21, 2017 at 16:31

1 Answer 1

19

You can only use await inside of an async function. If you have a non-async function nested inside of an async function, you can't use await in that function:

async function load() {
    return await new Promise((resolve, reject) => {
        TableImport.findAll().then((tables) => {
           for (let table of tables) {
               await loadData(table.fileName, table.tableName);

You have a callback to the .then method above. This callback is not async. You could fix this by doing async tables => {.

However since load is async and findAll returns a promise, you don't need to use .then:

async function load() {
    const tables = await TableImport.findAll();
    for (let table of tables) {
        await loadData(table.fileName, table.tableName);
    }
}

I'm not exactly sure what loadData does and if you have to load the tables in order, but you can also parallelize this:

const tables = await TableImport.findAll();
const loadPromises = tables.map(table => loadData(table.fileName, table.tableName));
await Promise.all(loadPromises);
  • The return await is superfluous since you are already returning a promise. Just return will work.
  • If you rewrite as I suggested, you don't need to use a Promise object since the methods you are working with return promises anyway.
  • Your original function was resolving nothing, so this function works the same by returning nothing.
  • Your original function was also propagating an error with reject(err). This function does not handle an error internally so it will also propagate the error in the same way.

Your loadData function can also be rewritten and simplified quite a bit:

function loadData(location, tableName) {
    const currentFile = path.resolve(__dirname + '/../fdb/' + location);
    return sequelize.query("LOAD DATA LOCAL INFILE '" + currentFile.replace('/', '//').replace(/\\/g, '\\\\') + "' INTO TABLE " + tableName + " FIELDS TERMINATED BY '|'");
};
  • loadData doesn't need to be async since you don't use await. You are still returning a promise.
  • You may want to add .catch since in your original code you didn't return an error. My code above will return the error caused by .query.
  • You pass the table name in and you don't actually do anything with the return value, so I just removed the .then entirely.
Sign up to request clarification or add additional context in comments.

7 Comments

OK right... made all those changes... i understand all of your comments but one question. The following does not work: async function load() { return await new Promise((resolve, reject) => { const tables = await TableImport.findAll() ; when i remove the new Promise it works... Can you explain why?
also this statement sort of threw me a little: If you have a non-async function nested inside of an async function, you can't use await in that function: but i made LOADDATA non-async and i can call that with await--it works....
I think you mean function loadData { return aPromise; } ... async function load() { await loadData(); }. The use of async/await has to do with scope. loadData is not in the load function scope. it's just being called in that scope.
kind of weird that LOADDDATA i know returns promise but when you add to promise array it runs the function on each row... not when the promise.all is called...
@user3597741 it's supposed to do that. It's just that it will wait for them all to finish before Promise.all resolves
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.