JavaScript API - Почему отображается только одна пара ключ / пол JSON?

1

Я тестирую API на страницах Github. Я смог использовать API Openweather.org. Полные данные JSON можно просмотреть в браузере, но только одна пара ключ/значение, "описание", будет отображаться на моей странице. Я попытался добавить три тега div в HTML, используя двоеточие между погодой и ключом, который я хочу отобразить, и я попытался использовать только одну точку. Я погуглил эту проблему, но не нашел ничего, что относится к моему проекту.

Также обратите внимание, что я закомментировал две переменные, const t и const m, потому что они приводят к сбою программы. Я пытался скопировать формат const p. Любое руководство будет оценено !!

Вот данные о погоде JSON:

{
    coord: {
        lon: -0.13,
        lat: 51.51
    },
    weather: [
        {
            id: 701,
            main: "Mist",
            description: "mist",
            icon: "50n"
        }
    ],
    base: "stations",
    main: {
        temp: 278.61,
        pressure: 1024,
        humidity: 81,
        temp_min: 276.15,
        temp_max: 280.15
    },
    visibility: 10000,
    wind: {
        speed: 3.1,
        deg: 100
    },
    clouds: {
        all: 20
    },
    dt: 1544552400,
    sys: {
        type: 1,
        id: 1414,
        message: 0.0033,
        country: "GB",
        sunrise: 1544515001,
        sunset: 1544543482
    },
    id: 2643743,
    name: "London",
    cod: 200
}

Вот мой JavaScript:

//added strict mode to address following error message, "Uncaught SyntaxError: Unexpected token u in JSON at position 0."   'use strict';

const app = document.getElementById("root");

//add API related image
const weather = document.createElement("img");
weather.src = "weather.jpg";

const container = document.createElement("div");
container.setAttribute("class", "container");

//method to append the logo image and container div to the app root.
app.appendChild(weather);
app.appendChild(container);

// Create a request variable and assign a new XMLHttpRequest object to it.
var request = new XMLHttpRequest();

// Open a new connection, using the GET request on the URL endpoint
request.open("GET", "https://api.openweathermap.org/data/2.5/weather?q=London&APPID=14d276f4fe655e659ec92149c7cebbec", true);

request.onload = function () {    

    // Begin accessing JSON data here

    var data = JSON.parse(this.response);
      if (request.status >= 200 && request.status < 400) {
        data.weather.forEach(weather => {
          const card = document.createElement("div");
          card.setAttribute("class", "card");
          const h1 = document.createElement("h1");
          h1.textContent = weather.title;

          const p = document.createElement("p");
          weather.description = weather.description.substring(0, 300);
          p.textContent = '${weather.description}...';

          /*const m = document.createElement("p");
          weather.main = weather.main.substring(0, 300);
          m.textContent = '${weather.main}...';

          const t = document.createElement("p");
          weather.main.temp = weather.main.temp;
          t.textContent = '${weather.main.temp}...'; */

          // Append the cards to the container element
          container.appendChild(card);

          // Each card will contain an h1 and a p    
          card.appendChild(h1);
          card.appendChild(p);
        });
      } else {
        const errorMessage = document.createElement("marquee");
        errorMessage.textContent = 'Hug it, it not working!';
        app.appendChild(errorMessage);
      }
    }
    // send request
    request.send();

Вот HTML-код:

  <!DOCTYPE html>
   <html lang="en">

   <head>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">

   <title>API Testing</title>

  <link href="https://fonts.googleapis.com/css?family=Dosis:400,700" 
   rel="stylesheet">
  <link href="/style.css" rel="stylesheet">

</head>

<body>

  <div id="root"></div>
     <script src="/scripts.js"></script>
</body>

</html>

Вот CSS:

* {
  box-sizing: border-box
}

html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-family: 'Dosis', sans-serif;
  line-height: 1.6;
  color: #666;
  background: #F6F6F6;
}

#root {
  max-width: 1200px;
  margin: 0 auto;
}

h1 {
  text-align: center;
  padding: 1.5rem 2.5rem;
  background-image: linear-gradient(120deg, #fbc2eb 0%, #a6c1ee 100%);
  margin: 0 0 2rem 0;
  font-size: 1.5rem;
  color: white;
}

p,t {
  padding: 0 2.5rem 2.5rem;
  margin: 0;
}

.container {
  display: flex;
  flex-wrap: wrap;
}

.card {
  margin: 1rem;
  background: white;
  box-shadow: 2px 4px 25px rgba(0, 0, 0, .1);
  border-radius: 12px;
  overflow: hidden;
  transition: all .2s linear;
}

.card:hover {
  box-shadow: 2px 8px 45px rgba(0, 0, 0, .15);
  transform: translate3D(0, -2px, 0);
}

@media screen and (min-width: 600px) {
  .card {
    flex: 1 1 calc(50% - 2rem);
  }
}

@media screen and (min-width: 900px) {
  .card {
    flex: 1 1 calc(33% - 2rem);
  }
}

.card:nth-child(2n) h1 {
  background-image: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);
}

.card:nth-child(4n) h1 {
  background-image: linear-gradient(120deg, #ff9a9e 0%, #fecfef 100%);
}

.card:nth-child(5n) h1 {
  background-image: linear-gradient(120deg, #ffc3a0 0%, #ffafbd 100%);
}
  • 0
    Мне неясно, с какой проблемой вы столкнулись. Я вижу ошибку в вашем примере javascript о синтаксическом анализе результата от вашего вызова API. Это проблема, о которой вы говорите? Или что-то еще целиком? SyntaxError: Unexpected token u in JSON at position 0."
  • 0
    @RyanWilson Это было сообщение об ошибке, которое я решил на прошлой неделе. Я добавил это в комментариях, чтобы напомнить себе, почему я использовал строгий режим. В настоящее время не должно быть никаких сообщений об ошибках.
Показать ещё 15 комментариев
Теги:
openweathermap

2 ответа

0

Эта проблема:

Как обсуждал Райан Уилсон, проблема, с которой вы сталкиваетесь, заключается в том, что вы пытаетесь получить доступ к параметрам, которых нет в свойстве weather вашего JSON, пока вы просматриваете свойство weather. Чтобы помочь вам понять это, рассмотрите следующий JSON (усеченный из используемого вами API):

data = {
    weather: [
                {
                    id: 721,
                    main: "Haze",
                    description: "haze",
                    icon: "50n"
                },
                {
                    id: 300,
                    main: "Drizzle",
                    description: "light intensity drizzle",
                    icon: "09n"
                },
                {
                    id: 701,
                    main: "Mist",
                    description: "mist",
                    icon: "50n"
                }
            ],
    base: "stations",
    main: {
                temp: 278.37,
                pressure: 1023,
                humidity: 87,
                temp_min: 276.15,
                temp_max: 280.15
           }
    id: 2643743,
    name: "London",
    cod: 200
};

У этого объекта JSON есть несколько уровней. Если я хочу получить доступ к туманной погоде, мне придется использовать data.weather [2].main, который будет возвращать "Mist". Это потому, что я выбираю свойство 'main' из третьего элемента массива погоды.

Теперь, если бы я попытался получить 'temp' с помощью data.weather [2].main.temp, он ничего бы не возвратил, потому что нет никакого свойства 'temp' под третьим объектом погоды. Однако есть временное свойство под основным объектом в корне объекта данных. Для доступа к этому вам нужно будет использовать data.main.temp.

Как это относится к вашему коду?

Если вы посмотрите на свой код, вы просматриваете массив data.weather, используя:

data.weather.forEach(weather => {
    //...
});

Для каждой итерации этого блока переменная weather будет равняться одному из объектов в массиве data.weather. Так что, если вы должны были использовать:

data.weather.forEach(weather => {
    console.log(weather.main);
});

Вы получите "дымку", затем "морось", затем "туман". (На основе JSON, который я показал выше).

Я полагаю, что вы многое выяснили, но затем вы попытались получить температуру с помощью weather.main.temp, который не является допустимым параметром. Вместо этого вам придется использовать data.main.temp.

Я надеюсь, что это немного прояснит для вас JSON.

Реальный ответ:

Реальный ответ на ваш вопрос "Почему он показывает только одну пару ключ-значение?" на самом деле не имеет ничего общего с тем, что я сказал выше. Если бы вы посмотрели на JSON, который API отправлял при публикации вопроса, вы бы увидели, что в массиве погоды был только один объект. На момент написания статьи их было три. Ваш код создаст только столько карт, сколько есть элементов в массиве погоды.

Обязательно обращайтесь к Райану Уилсону JSFiddle здесь: https://jsfiddle.net/ep84so9m/2/ Он изменил ваш код, чтобы сделать то, что, по-вашему, было после.

Надеюсь, это поможет!

  • 0
    Хорошее объяснение. Хорошо продумано и объяснено. +1
  • 0
    @ Райан Гиббс Спасибо, Райан, это очень помогает! Один быстрый вопрос. Почему вам нужно использовать «данные» для временного, а не для описания? Смотрите ниже: temp.textContent = ${data.main.temp}... ; description.textContent = ${weather.description}... ; Похоже, это тоже должно быть data.weather.description.
Показать ещё 1 комментарий
0

Похоже, вы получаете ответ API в виде JSON object поэтому вызов JSON.parse() вызывает ошибку, попробуйте изменить эту строку:

var data = JSON.parse(this.response);

TO:

var data = this.response;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню