【问题标题】:Global variable doesn't keep value after being changed in node全局变量在节点中更改后不保留值
【发布时间】:2019-06-01 03:29:19
【问题描述】:

我的问题是我的代码在 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,而不是预期的结果&lt;The Champion's Name&gt;

观察到的输出:

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 中异步的理解的错误,但我不确定。

【问题讨论】:

  • 你应该只使用await 承诺。 .readFile 不返回 Promise
  • 我去掉了 await 但观察到的输出还是一样
  • 阅读链接的问题。
  • @CertainPerformance 我阅读了链接的问题,但我仍然不明白。我只是不确定为什么 champName = champsJson[i].championName; 行没有将 champName 分配给 champsJson[i].championName 该函数之外的任何地方,这就是为什么最后一个打印没有显示冠军名称的原因。

标签: node.js asynchronous scope


【解决方案1】:

解决方案是将方法调用从 fs.readFile 更改为 fs.readFileSync。

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

并在该分配之后移动 for 循环。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 2011-11-18
      相关资源
      最近更新 更多