嵌套异步/等待Nodejs
似乎无法弄清楚为什么这对我不起作用。我有一个父函数在子加载进程上执行AWAIT ... LOAD进程依次调用另一个叫做LOADDATA的AWAIT ...所以基本上是这样的:
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();
});
});
};
LOAD中的AWAIT失败说明:
await loadData(table.fileName,table.tableName); SyntaxError:意外的标识符
显然不了解异步的范围!
回答如下:你只能在异步函数中使用await
。如果嵌套在异步函数中的非异步函数,则不能在该函数中使用await
:
async function load() {
return await new Promise((resolve, reject) => {
TableImport.findAll().then((tables) => {
for (let table of tables) {
await loadData(table.fileName, table.tableName);
你有回调上面的.then
方法。此回调不是异步。你可以通过做async tables => {
解决这个问题。
然而,由于load
是异步的并且findAll
返回一个承诺,你不需要使用.then
:
async function load() {
const tables = await TableImport.findAll();
for (let table of tables) {
await loadData(table.fileName, table.tableName);
}
}
我不确定loadData
做了什么,如果你必须按顺序加载表,但你也可以并行化这个:
const tables = await TableImport.findAll();
const loadPromises = tables.map(table => loadData(table.fileName, table.tableName));
await Promise.all(loadPromises);
return await
是多余的,因为你已经回复了一个承诺。只是return
将工作。- 如果按照我的建议重写,则不需要使用Promise对象,因为您正在使用的方法无论如何都会返回promise。
- 你的原始函数什么都没解析,所以这个函数通过什么都不返回来工作。
- 您的原始函数也在使用
reject(err)
传播错误。此函数不会在内部处理错误,因此它也会以相同的方式传播错误。
你的loadData
函数也可以重写和简化:
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
不需要异步,因为你不使用await
。你还在回复诺言。- 您可能想要添加
.catch
,因为在原始代码中您没有返回错误。我上面的代码将返回.query
引起的错误。 - 你传递了表名,你实际上并没有对返回值做任何事情,所以我完全删除了
.then
。