简体   繁体   中英

Problem with getting e.target value from an asynchronous function

I've got a little problem with getting value from an asynchronous function and then use it in the e.target function. I want to be able to click one of two lists (names and surnames) and then show in the div called 'result' the result. I read lots of articles but none of them was straight accurate to my problem:( What am I doing wrong?

 async function getData() { let url = 'http://www.json-generator.com/api/json/get/cuSKqtKmgi?indent=2'; try { let res = await fetch(url); return await res.json(); } catch (error) { console.log(error); } } async function renderUsers() { const nameList = document.querySelector('.name-list') const surnameList = document.querySelector('.surname-list') let data = await getData(); let names = ''; let surnames = ''; data.person.forEach(user => { let htmlSegment = ` <li>${user.name}</li> `; names += htmlSegment; }); data.person.forEach(user => { let htmlSegment = ` <li>${user.surrname}</li> `; surnames += htmlSegment; }); nameList.innerHTML = names; surnameList.innerHTML = surnames; } const chooseUser = (e) => { const result = document.querySelector('.result') const origin = e.target; result.textContent = origin.textContent; } const showUser = () => { const menu = document.querySelectorAll('ul li') menu.forEach(element => { element.addEventListener('click', chooseUser) }); } renderUsers(); showUser()
 nav{ display: flex; justify-content: flex-start; } ul li{ cursor: pointer; }
 <nav> <ul class="name-list"> </ul> <ul class="surname-list"> </ul> </nav> <div class="result"></div>

If something is unclear feel free to ask:)

renderUsers().then(r=>{
    showUser()
})

Why?:
renderUsers is async function

so, without then(... ) , showUser() will called before render items. so, const menu = document.querySelectorAll('ul li') will return empty list

Lots of things I would fix in this program -

  • Keep functions synchronous wherever possible
  • Functions should take arguments and return results
  • Write generic functions that can be reused
  • Using .innerHTML to build complex documents forces all of your data through the String interface
  • Error handling should not be part of your fetching function. Let the caller decide what to do

 const getJSON = url => // <- generic fetch(url).then(r => r.json()) function li(text) { const e = document.createElement("li") // <- use DOM api e.textContent = text return e // <- returns value } function appendUsers(elem, users) { const names = elem.querySelector(".name-list") const surnames = elem.querySelector(".surname-list") for (const u of users) { names.appendChild(li(u.name)) // <- DOM api surnames.appendChild(li(u.surrname)) } } const showUser = (elem, name) => elem.textContent = name async function main(url) { const nav = document.querySelector("nav") // <- once const result = document.querySelector("#result") // <- once const data = await getJSON(url) // <- generic appendUsers(nav, data.person) // <- synchronous nav.addEventListener("click", e => { showUser(result, e.target.textContent) }) } main("http://www.json-generator.com/api/json/get/cuSKqtKmgi?indent=2").catch(console.error) // <- err handler
 nav{ display: flex; justify-content: flex-start; } ul li{ cursor: pointer; }
 <nav> <ul class="name-list"> </ul> <ul class="surname-list"> </ul> </nav> <div id="result"></div>

Well the renderUsers is async, so at the time you call showUser there are no li elements to be selected. You could call showUser at the end of renderUsers or just create async block and await for renderUsers to resolve first.

 async function getData() { let url = 'https://www.json-generator.com/api/json/get/cuSKqtKmgi?indent=2'; try { let res = await fetch(url); return await res.json(); } catch (error) { console.log(error); } } async function renderUsers() { const nameList = document.querySelector('.name-list') const surnameList = document.querySelector('.surname-list') let data = await getData(); let names = ''; let surnames = ''; data.person.forEach(user => { let htmlSegment = `<li>${user.name}</li>`; names += htmlSegment; }); data.person.forEach(user => { let htmlSegment = ` <li>${user.surrname}</li>`; surnames += htmlSegment; }); nameList.innerHTML = names; surnameList.innerHTML = surnames; } const chooseUser = (e) => { const result = document.querySelector('.result') const origin = e.target; result.textContent = origin.textContent; } const showUser = () => { const menu = document.querySelectorAll('ul li') menu.forEach(e => e.addEventListener('click', chooseUser)); } (async() => { await renderUsers(); showUser() })()
 nav { display: flex; justify-content: flex-start; } ul li { cursor: pointer; }
 <nav> <ul class="name-list"> </ul> <ul class="surname-list"> </ul> </nav> <div class="result"></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM