Глобальная переменная не сохраняет значения после изменения в узле - PullRequest
0 голосов
/ 06 января 2019

Моя проблема в том, что мой код назначает champName другому значению внутри функции в вызове readfile. Однако после завершения вызова champName не сохраняет это значение, даже если оно объявлено глобально для этой функции. Как мне это исправить?

Код ниже - это то, что у меня есть сейчас. Ранее я пытался использовать цикл for вне функции, но тогда я получал бы ошибки о cannot read property 'length' of undefined, хотя undefined должен быть champsJson, который был определен ранее, а это означает, что champsJson не обновляется вне этого метода.

//This function takes in a champId (number) and returns the appropriate 
//string that is associated with that champId
function decipherChamp(champId) {
    //Local variables
    var champName = 'This should never print';
    var champsJson = ''

    //Reads champions.json into rawData
    fs.readFile('./commands/lol/champions.json', 'utf8', function (err, data) {
        if (err)
            throw err;
        champsJson = JSON.parse(data);
        for (let i = 0; i < champsJson.length; i++) {
            if (champsJson[i].championId == champId) {
                champName = champsJson[i].championName;
                console.log("champName inside fn: " + champName)
            }
        }
    });
    console.log("champName before return: " + champName)
    return champName
}    

Я добавил console.log("champName before return: " + champName), чтобы увидеть, что champName перед печатью, и он печатает This should never print, инициализированное значение вместо ожидаемого результата, <The Champion's Name>

Наблюдаемый вывод:

Running command lol:currgame. champName before return: This should never print champName inside fn: Brand champName before return: This should never print champName inside fn: Graves champName before return: This should never print champName inside fn: Tristana champName before return: This should never print champName inside fn: Jax champName before return: This should never print champName inside fn: Malzahar champName before return: This should never print champName inside fn: Thresh champName before return: This should never print champName inside fn: Galio champName before return: This should never print champName inside fn: Kai'Sa champName before return: This should never print champName inside fn: Trundle champName before return: This should never print champName inside fn: Kennen

Ожидаемый результат:

Running command lol:currgame. champName before return: Brand champName inside fn: Brand champName before return: Graves champName inside fn: Graves champName before return: Tristana ...

Я также заметил, что он печатает champName до возврата перед внутренним результатом функции, что заставляет меня поверить, что это ошибка с моим пониманием асинхронности в узле, но я не уверен.

Ответы [ 2 ]

0 голосов
/ 06 января 2019

Использование fs.readFileSync() допустимо, но не обязательно является хорошим решением.

Операции синхронизации в узле (например, файловый ввод / вывод) могут блокировать и непредвиденным образом повлиять на ваше приложение. Лучшим решением было бы использовать

const { promisify } = require('util');
const asyncReadFile = promisify(fs.readFile);

вверху вашего файла и замените код decipherChamp() на что-то вроде следующего:

async function decipherChamp ( champId )

    let champName = `Never see me...`;
    let champData;

    try {
        const file = await asyncReadFile(...);
        champData = JSON.parse(file);
    }
    catch (e) { 
        console.error(e); // error handling - failed to read file
        champName = `FAILED!`; // or whatever when error occurs
    }

    const champ = champData.find(champ => champ.championId == champId);
    if ( champ ) {
        champName = champ.champName;
    }
    console.log(...);
    return champName;
}
0 голосов
/ 06 января 2019

Решением было изменить вызов метода с fs.readFile на fs.readFileSync.

champsJson = JSON.parse(fs.readFileSync('./commands/lol/champions.json', 'utf8'))

и переместить цикл for после этого присваивания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...