【问题标题】:Trying to access JSON data throws error on first click, but works on second click尝试访问 JSON 数据在第一次单击时会引发错误,但在第二次单击时有效
【发布时间】:2022-01-22 10:13:22
【问题描述】:

我正在构建一个简单的应用程序,它可以访问 API 并呈现信息。它由按钮中的事件侦听器激活,该侦听器获取 html 输入字段的值并将其插入到我的 apiCall 函数中。然后我的代码处理 api 响应并将所需的数据分配给对象内部的变量,然后 console.log'ged out。

这是我的问题:当我第一次单击按钮时,我收到以下错误消息:

Uncaught TypeError: Cannot read properties of undefined (reading 'average_price')
    at Object.getAveragePrice (index.js:17)
    at render (index.js:27)
    at HTMLButtonElement.<anonymous> (index.js:33)

然后我第二次单击该按钮,我在控制台中获得了正确的数据。我究竟做错了什么?下面是我的javascript。

let jsonResponse = ""
let collectionName = ""
let inputEl = document.getElementById("input-el")
let buttonEl = document.getElementById("button-el")


function callApi(collectionName) {
    fetch(`https://api.opensea.io/api/v1/collection/${collectionName}/stats`)
    .then(response => response.json())
    .then(response => jsonResponse = response)
    .catch(err => console.error(err));
}

const getJsonData = {
    getAveragePrice: function() {
        collectionData.averagePrice = jsonResponse.stats["average_price"]
    }
}

let collectionData = {
    averagePrice: ""
}

function render() {
    callApi(collectionName)
    getJsonData.getAveragePrice()
    console.log(JSON.stringify(collectionData.averagePrice))
}

buttonEl.addEventListener("click", () => {
    collectionName = inputEl.value
    render()
})

【问题讨论】:

  • 因为您正在调用异步函数,然后尝试在它有机会完成之前访问它的结果。有很多关于此的 SO 帖子

标签: javascript html json api


【解决方案1】:

我发现您的代码有几个问题,您遇到的问题是:

首先,这是因为jsonResponse 的初始值是一个字符串,而您将它作为一个对象访问。

let jsonResponse = ""

但您以以下方式访问它:

jsonResponse.stats["average_price"]

将默认值更改为此将修复错误:

let jsonResponse = {
  stats: {
    average_price: 0
  }
}

但是,这将“无法修复”您的逻辑,因为您所期望的是 callApi 在触发 getJsonData.getAveragePrice() 之前已完成调用。

这是您需要使用 async/await 或 promise 来实现这一点的第二个问题。

我在代码改进上添加了一些 cmets:

function callApi(collectionName) {
    // return the promise
    return fetch(`https://api.opensea.io/api/v1/collection/${collectionName}/stats`)
    .then(response => response.json())
    .then(response => jsonResponse = response)
    .catch(err => console.error(err));
}

// make this function async
async function render() {
    // add await on call API so it will finish the promise first
    await callApi(collectionName)
    getJsonData.getAveragePrice()
    console.log(JSON.stringify(collectionData.averagePrice))
}

buttonEl.addEventListener("click", async () => {
    collectionName = inputEl.value
    await render()
})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-23
    • 2013-01-06
    • 1970-01-01
    • 2015-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多