node.js - 嵌套异步/等待 Nodejs

标签 node.js asynchronous async-await

似乎无法弄清楚为什么这对我不起作用。我有一个在子加载进程上执行 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 失败说明:

等待 loadData(table.fileName, table.tableName); 语法错误:意外的标识符

显然不了解异步范围!

最佳答案

您只能在异步函数中使用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 返回一个 promise ,您不需要使用 .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 是多余的,因为您已经返回了一个 promise 。只需 return 即可。
  • 如果您按照我的建议重写,则无需使用 Promise 对象,因为您正在使用的方法无论如何都会返回 promises。
  • 您的原始函数没有解析任何内容,因此此函数的工作原理相同,但不返回任何内容。
  • 您的原始函数还使用 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。你仍然在返回一个 promise 。
  • 您可能想要添加 .catch,因为在您的原始代码中您没有返回错误。我上面的代码将返回由 .query 引起的错误。
  • 你传递了表名,实际上你没有对返回值做任何事情,所以我只是完全删除了 .then

关于node.js - 嵌套异步/等待 Nodejs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47928992/

相关文章:

javascript - 我想我不会 "get"异步编程

php - 与使用 PHP 等为移动应用程序创建的普通 API 相比,将 Node.js 用于 API 有什么好处吗?

javascript - 它添加了第二个 } 并且不会在级别上添加 1

javascript - 在从我的 promise /功能返回之前等待 forEach 完成

javascript - 如何使用 bluebird 正确地 promise JSON.parse 方法

javascript - await 不是保留字

javascript - 如何在 JavaScript 中从 char 获取 make 代码?

node.js - 我可以检查异步函数是否正在运行吗?

c# - 正确使用异步和等待

javascript - 如何中止(停止)循环执行的 promise 链? - JavaScript