我的问题是我的代码将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,这使我相信这是我对节点异步的理解的一个错误,但是我不确定。
答案 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;
}