Как установить addEventListener на ввод автозаполнения и предоставить несколько исходных обратных вызовов и использовать их один за другим

Я пытаюсь установить addEventListener на входе, когда он будет меняться, я хочу вызвать функцию с помощью fetch api У меня есть автозаполнение с названиями городов, моя цель - получить информацию по выбранному названию города а во-вторых, может быть кто-то знает, как оптимизировать этот код с вызовом обратных вызовов и использовать их один за другим, пока результат обратного вызова не вернет не пустой массив.

Теперь у меня есть входные данные с названиями городов (полученные API для json), но консоль показывает мне, что входное значение не определено, когда я выбираю какой-либо город

у меня есть js-файл:

let cities = document.querySelector("#languageList");
let cityInfoContainer = document.querySelector(".cityInfoContainer");
let input = document.querySelector("#txtAutoComplete");



  fetch("https://katehrybkova.github.io/CItiesFilter/src/analytics/fixtures/cities.json")
  .then(res => res.json())
  .then((data) => {
     data.map(el=>cities.innerHTML += `<option value=${el.city}>`)
  })
  .catch(err => { throw err });


  let getCityInfo = (cityName) => fetch(`https://katehrybkova.github.io/CItiesFilter/src/analytics/fixtures/data/${cityName.toLowerCase()}`)
  .then(res => res.json())
  .then((data) => {
    data.map(city => city.map(el=>cityInfoContainer.innerHTML += `<p> ${el.year}</p>`))
  })
  .catch(err => { throw err });

  input.addEventListener("change", getCityInfo(this.value))

и HTML

    <header></header>
    <main class = "cityInfo">
        <form>
            <input type = "text" id = "txtAutoComplete" list = "languageList" />
            <datalist id = "languageList">
            </datalist>
        </form>
        <div class = "cityInfoContainer"></div>

    </main>
    <footer></footer>
    <script src = "./dist/main.js"></script>
</body>```
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
1 038
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Вы должны использовать Promises (или async-await)
  2. Вы забыли .json в конце запроса City Info API.
  3. .карта() возвращает новый массив. Вам нужен .для каждого() для этой функции
  4. Нужен был только один .для каждого() (поэтому не карта в карте), так как массив был только на один уровень в глубину

let cities = document.querySelector("#languageList");
let cityInfoContainer = document.querySelector(".cityInfoContainer");
let input = document.querySelector("#txtAutoComplete");

getCityNames()
  .then(data => {
    data.map(el => cities.innerHTML += `<option value=${el.city}>`)
  })

input.addEventListener("change", function(e) {
  getCityInfo(this.value)
    .then(data => {
      console.info(data)
      // this clears the area for the new city selected
      if (cityInfoContainer.innerHTML !== '') {
        cityInfoContainer.innerHTML = ''
      }
      data.forEach(city => cityInfoContainer.innerHTML += `<p> ${city.year} ${city.population}</p>`)
    })
    .catch(err => {
      console.info('err', err)
    })
})

function getCityNames() {
  return new Promise((resolve, rejecet) => {
    fetch("https://katehrybkova.github.io/CItiesFilter/src/analytics/fixtures/cities.json")
      .then(res => res.json())
      .then((data) => {
        resolve(data)
      })
      .catch(err => {
        reject(err)
      });
  })
}

function getCityInfo(cityName) {
  return new Promise((resolve, reject) => {
    fetch(`https://katehrybkova.github.io/CItiesFilter/src/analytics/fixtures/data/${cityName.toLowerCase()}.json`)
      .then(res => res.json())
      .then((data) => {
        resolve(data)
      })
      .catch(err => {
        reject(err)
      });
  })
}
<main class = "cityInfo">
  <form>
    <input type = "text" id = "txtAutoComplete" list = "languageList" />
    <datalist id = "languageList">
            </datalist>
  </form>
  <div class = "cityInfoContainer"></div>

</main>

Что касается вызова их по одному, пока вся информация не будет загружена:

let cities = document.querySelector("#languageList");
let cityInfoContainer = document.querySelector(".cityInfoContainer");
let input = document.querySelector("#txtAutoComplete");

// adding an array that will hold all the cities' names
let cityNameArr = []

getCityNames()
  .then(data => {
    data.forEach(el => cities.innerHTML += `<option value=${el.city}>`)
    return data.map(el => {
      return {
        cName: el.city
      }
    })
  })
  .then(cityNames => {
    return cityNames.map(el => {
      return {
        cName: el.cName,
        cInfo: getCityInfo(el.cName)
      }
    })
  })
  .then(city => {
    console.info(city) // expected to see "cInfo: Promise" - until it's resolved
  })



input.addEventListener("change", function(e) {
  getCityInfo(this.value)
    .then(data => {
      console.info(data)
      // this clears the area for the new city selected
      if (cityInfoContainer.innerHTML !== '') {
        cityInfoContainer.innerHTML = ''
      }
      data.forEach(city => cityInfoContainer.innerHTML += `<p> ${city.year} ${city.population}</p>`)
    })
    .catch(err => {
      console.info('err', err)
    })
})

function getCityNames() {
  return new Promise((resolve, rejecet) => {
    fetch("https://katehrybkova.github.io/CItiesFilter/src/analytics/fixtures/cities.json")
      .then(res => res.json())
      .then((data) => {
        resolve(data)
      })
      .catch(err => {
        reject(err)
      });
  })
}

function getCityInfo(cityName) {
  return new Promise((resolve, reject) => {
    fetch(`https://katehrybkova.github.io/CItiesFilter/src/analytics/fixtures/data/${cityName.toLowerCase()}.json`)
      .then(res => res.json())
      .then((data) => {
        resolve(data)
      })
      .catch(err => {
        reject(err)
      });
  })
}
<main class = "cityInfo">
  <form>
    <input type = "text" id = "txtAutoComplete" list = "languageList" />
    <datalist id = "languageList">
            </datalist>
  </form>
  <div class = "cityInfoContainer"></div>

</main>

Другие вопросы по теме