问题
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:
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. Justreturn
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 useawait
. 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.
来源:https://stackoverflow.com/questions/47928992/nested-async-await-nodejs