Javascript 如何确保JSON常量在JS中首先初始化

Javascript 如何确保JSON常量在JS中首先初始化,javascript,node.js,json,constants,es6-promise,Javascript,Node.js,Json,Constants,Es6 Promise,我是Javascript新手,我不知道为什么这是错误的 在下面的代码中,在一些运行中,它将声明playerwinrades是未定义的 TypeError: Cannot read property 'lost' of undefined at file:///Users/bergholm/projects/FACEITDiscordBot/faceIt.js:296:36 at Array.forEach (<anonymous>) at getPastMat

我是Javascript新手,我不知道为什么这是错误的

在下面的代码中,在一些运行中,它将声明playerwinrades是未定义的

TypeError: Cannot read property 'lost' of undefined
    at file:///Users/bergholm/projects/FACEITDiscordBot/faceIt.js:296:36
    at Array.forEach (<anonymous>)
    at getPastMatchesByPlayer (file:///Users/bergholm/projects/FACEITDiscordBot/faceIt.js:284:16)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
undefined
(node:35193) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
(node:35193) UnhandledPromiseRejectionWarning: TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at bestWinRate (file:///Users/bergholm/projects/FACEITDiscordBot/faceIt.js:341:20)
    at Client.<anonymous> (file:///Users/bergholm/projects/FACEITDiscordBot/bot.js:126:15)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:35193) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)

编辑:删除了函数说明,因为它占用了大量空间,并且对此任务没有帮助

我认为问题在于,您不能
数组中返回
。forEach()
,因此在没有值的地方,您不能中断循环。我刚刚将您的
forEach
切换到
for in
循环

很难在本地进行测试,但请让我知道这是否有效

异步函数getPastMatchesByPlayer(playerId,numMatches=20){ /*检索球员的最后20场比赛 FACEIT数据API GET/players/{player_id}/history 输入: 玩家id*字符串(路径)-玩家的id 游戏*字符串(查询)-FACEIT上的游戏 from integer(查询)-作为查询下限的时间戳(Unix时间)。如果未指定,则为1个月前 to integer(查询)-作为查询上限的时间戳(Unix时间)。如果未指定,则为当前时间戳 偏移整数(查询)-起始项目位置 限制整数(查询)-要返回的项数 请求URL-https://open.faceit.com/data/v4/players/20dcc7de-c82b-4d12-9bbd-b9c448b63888/history?game=csgo&offset=0&limit=20 */ const response=等待axios.get( "https://open.faceit.com/data/v4/players/" + playerId+ “/history?game=csgo&offset=0&limit=”+ numMatches ) 常数playerWinRates={ 德鲁缓存:{赢了:0,输了:0}, de_dust2:{赢了:0,输了:0}, 德鲁·海市蜃楼:{赢了:0,输了:0}, 德努克:{赢了:0,输了:0}, 德鲁立交桥:{原:0,失:0}, 德鲁火车:{赢:0,输:0}, 地狱之王:{赢了:0,输了:0}, de_眩晕:{赢了:0,输了:0}, } 让matchId=[] 让StatsPromissions=[] response.data.items.forEach((匹配)=>{ matchID.push(match.match\u id) statsPromises.push(parseMatchWon(比赛,玩家ID)) }) const listOfResults=等待承诺。全部(statsPromises) for(listOfResults中的常量listItem){ const mapWL=listOfResults[listItem] if(!Object.keys(mapWL.length){//if null--无法获取匹配项,因此忽略它 log(“进入空/未定义”) 返回; } 让map=Object.keys(mapWL)[0] 如果(地图=='won'| |地图=='lost'){ playerWinRates[map][mapWL[map]]+=1 } } //提供了匹配id,以便将来可以对其进行解析,以便在不同的匹配上获得更大的权重 返回{playerWinRates:playerWinRates,matchId:matchId}
}
因此,我在判断时犯了一个巨大的错误,因为我没有意识到faceit不仅仅有地图池,还有尽可能多的可以播放的地图

该常量将失败,因为名为“de_aimmap”的映射不作为键存在。我通过将错误抛出行更改为

if(playerWinRates[map])playerWinRates[map][key]+=1

async function getPastMatchesByPlayer(playerId, numMatches = 20) {
    
    const response = await axios.get(
        "https://open.faceit.com/data/v4/players/" +
            playerId +
            "/history?game=csgo&offset=0&limit=" +
            numMatches
    )
    const playerWinRates = {
        de_cache: { won: 0, lost: 0 },
        de_dust2: { won: 0, lost: 0 },
        de_mirage: { won: 0, lost: 0 },
        de_nuke: { won: 0, lost: 0 },
        de_overpass: { won: 0, lost: 0 },
        de_train: { won: 0, lost: 0 },
        de_inferno: { won: 0, lost: 0 },
        de_vertigo: { won: 0, lost: 0 },
    }

    let matchIds = []
    let statsPromises = []
    response.data.items.forEach((match) => {
        matchIds.push(match.match_id)
        statsPromises.push(parseMatchWon(match, playerId))
    })
    const listOfResults = await Promise.all(statsPromises)
    listOfResults.forEach((mapWL) => {
    if (!mapWL) { // If null -- failed to get match, so ignore it
      console.log("Went into null/undefined")
      return
    }
    let map = Object.keys(mapWL)[0]
    playerWinRates[map][mapWL[map]] += 1
    })
    // The match id's are provided so that in the future they could be parsed to allow for more weight on different matches
    return { playerWinRates: playerWinRates, matchIds: matchIds }
}

感谢格兰特·赫尔曼付出这么多的努力

嗯,这对我不起作用。我尝试了你的方法,并将if(!mapWL){…}改为if(mapWL){…}的相反形式,但这也不应该是问题所在。这并不是因为mapWL未定义或为空,而是因为playerWinRates未定义,您可以将条件更改为if(!Object.keys(mapWL.length){return}问题在于您如何对对象进行uodating,所以可能只需确保mapWL对象中首先有键。是否保证mapWL的密钥将映射到玩家的赢取率?我更新了代码以确保额外的安全性。因此,我们要确保mapWL对象中甚至有密钥,并且要确保它实际上等于赢或输。我对你的数据一无所知,但我认为这涵盖了你的基础。让我知道它是否有助于在
playerWinRates[map][mapWL[map]]+=1之前添加
console.log(mapWL,map)
,以查看失败的值。错误之前的最后一个日志将显示最后一个值。