全局变量在节点中更改后不保留值

时间:2019-01-06 01:37:07

标签: node.js asynchronous scope

我的问题是我的代码将champName分配给readfile调用中函数内的其他值。但是,调用结束后,即使champName已为该函数全局声明,它也不会保留该值。我该如何解决?

下面的代码是我现在拥有的。以前,我尝试在函数外使用for循环,但是即使未定义的应该是champsJson(先前已定义),我也会收到有关{-# LANGUAGE Rank2Types #-} fromInt :: Int -> (forall a. IntNat a -> r) -> r fromInt 0 f = f zero fromInt n f = fromInt (n - 1) (f . inc) 的错误,这意味着champsJson不会在该方法之外进行更新。

{-# LANGUAGE ExistentialQuantification #-}

data AnyIntNat = forall n. AnyIntNat (IntNat n)

fromInt :: Int -> AnyIntNat
fromInt 0 = AnyIntNat zero
fromInt n =
  case fromInt (n - 1) of
    AnyIntNat m -> AnyIntNat (inc m)

我添加了{-# LANGUAGE AllowAmbiguousTypes, DataKinds, FlexibleContexts, TypeApplications, TypeFamilies, TypeOperators, UndecidableInstances #-} import GHC.TypeLits class GetIntNat n where getIntNat :: IntNat n instance GetIntNat Z where getIntNat = zero instance GetIntNat n => GetIntNat (S n) where getIntNat = inc getIntNat type family Peano n where Peano 0 = Z Peano n = S (Peano (n - 1)) -- usage: fromNat @5 fromNat :: GetIntNat (Peano n) => IntNat (Peano n) fromNat = getIntNat 来查看champName在打印之前是正确的,它会打印cannot read property 'length' of undefined(已初始化的值),而不是预期的结果//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)

预期输出:

This should never print

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

2 个答案:

答案 0 :(得分:0)

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

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

,并在分配后移动for循环。

答案 1 :(得分:0)

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