首页 > 解决方案 > 全局变量在节点中更改后不保留值

问题描述

我的问题是我的代码在 readfile 调用中将 champName 分配给函数内部的不同值。但是,调用结束后,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 ...

我还注意到它在函数结果内部之前的 return 之前打印了 champName,这让我相信这是我对节点中异步的理解的错误,但我不确定。

标签: node.jsasynchronousscope

解决方案


使用fs.readFileSync()是有效的,但不一定是一个好的解决方案。

Node 中的同步操作(例如文件 I/O)可能会阻塞并以意想不到的方式影响您的应用程序。更好的解决方案是使用

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

推荐阅读