web-dev-qa-db-fra.com

Async imbriqué / Nodejs en attente

Je n'arrive pas à comprendre pourquoi cela ne fonctionne pas pour moi. J'ai une fonction parent qui exécute un AWAIT sur un processus de chargement enfant ... le processus LOAD appelle à son tour un autre AWAIT appelé LOADDATA ... donc en gros comme ceci:

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();
        });
    });
};

l'AWAIT dans la CHARGE échoue en déclarant:

attendre loadData (table.fileName, table.tableName); SyntaxError: Identifiant inattendu

De toute évidence, ne comprends pas quelque chose sur la portée de l'async!

6
user3597741

Vous ne pouvez utiliser que await à l'intérieur d'une fonction asynchrone. Si vous avez une fonction non asynchrone imbriquée à l'intérieur d'une fonction asynchrone, vous ne pouvez pas utiliser await dans cette fonction:

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

Vous avez un rappel de la méthode .then Ci-dessus. Ce rappel n'est pas asynchrone. Vous pouvez résoudre ce problème en faisant async tables => {.

Cependant, puisque load est asynchrone et que findAll renvoie une promesse, vous n'avez pas besoin d'utiliser .then:

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

Je ne sais pas exactement ce que fait loadData et si vous devez charger les tables dans l'ordre, mais vous pouvez également paralléliser ceci:

const tables = await TableImport.findAll();
const loadPromises = tables.map(table => loadData(table.fileName, table.tableName));
await Promise.all(loadPromises);
  • Le return await Est superflu puisque vous retournez déjà une promesse. Juste return fonctionnera.
  • Si vous réécrivez comme je l'ai suggéré, vous n'avez pas besoin d'utiliser un objet Promise puisque les méthodes avec lesquelles vous travaillez retournent de toute façon des promesses.
  • Votre fonction d'origine ne résolvait rien, donc cette fonction fonctionne de la même façon en ne renvoyant rien.
  • Votre fonction d'origine propageait également une erreur avec reject(err). Cette fonction ne gère pas une erreur en interne, elle propagera donc également l'erreur de la même manière.

Votre fonction loadData peut également être réécrite et simplifiée un peu:

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 n'a pas besoin d'être asynchrone car vous n'utilisez pas await. Vous renvoyez toujours une promesse.
  • Vous voudrez peut-être ajouter .catch Car dans votre code d'origine, vous n'avez pas renvoyé d'erreur. Mon code ci-dessus renverra l'erreur causée par .query.
  • Vous passez le nom de la table et vous ne faites rien avec la valeur de retour, donc je viens de supprimer complètement le .then.
12
Explosion Pills