【问题标题】:How to ensure JSON constant initialized first in JS如何确保在 JS 中首先初始化 JSON 常量
【发布时间】:2020-11-02 15:32:25
【问题描述】:

我是 Javascript 新手,不知道为什么会出错。

在下面的代码中,在 一些 运行时,它会声称 playerWinRates 未定义

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)

我说的代码sn-p在这里,在playerWinRates[map][mapWL[map]] += 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 }
}

编辑:删除了功能描述,因为它占用了大量空间并且对这项任务没有帮助

【问题讨论】:

  • playerWinRates[map][mapWL[map]] += 1 之前添加console.log(mapWL, map) 以查看失败的值。错误之前的最后一个日志将显示最后一个值。

标签: javascript node.js json constants es6-promise


【解决方案1】:

我认为问题在于您不能将return 排除在Array.forEach() 之外,因此在没有价值的情况下,您不跳出循环。我刚刚将您的 forEach 切换为 for in 循环。

很难在本地测试,但如果可行,请告诉我。

async function getPastMatchesByPlayer(playerId, numMatches = 20) {
/*  Retrieves the last 20 matches of the player
  FACEIT Data API GET /players/{player_id}/history
   Input:
   player_id * string (path) - The id of the player
   game * string (query) - A game on FACEIT
   from integer (query) - The timestamp (Unix time) as lower bound of the query. 1 month ago if not specified
   to integer (query) - The timestamp (Unix time) as higher bound of the query. Current timestamp if not specified
   offset integer (query) - The starting item position
   limit integer (query) - The number of items to return

   Request URL - https://open.faceit.com/data/v4/players/20dcc7de-c82b-4d12-9bbd-b9c448b63888/history?game=csgo&offset=0&limit=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)
for(const listItem in listOfResults){
  const mapWL = listOfResults[listItem]
  if (!Object.keys(mapWL).length) { // If null -- failed to get match, so ignore it
    console.log("Went into null/undefined")
    return;
  }
  let map = Object.keys(mapWL)[0]
  if(map === 'won' || map === 'lost'){
    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} 问题在于您如何处理对象,所以也许只需确保在首先是 mapWl 对象。是否保证 mapWL 的键会映射到玩家胜率?
  • 我更新了代码以更加安全。因此,我们确保该 mapWL 对象中甚至有键,并确保它实际上等于赢或输。我对您的数据一无所知,但我认为这涵盖了您的基础。让我知道是否有帮助
【解决方案2】:

所以我在判断上犯了一个巨大的错误,因为我没有意识到faceit除了地图池之外还有更多可以玩的地图。

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

来解决此问题

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 2020-01-04
    • 2019-09-06
    • 2021-02-11
    相关资源
    最近更新 更多