简体   繁体   中英

Javascript wait for Promises to return data then assign onClick event listener to perform action on returned data

(UPDATE: I'm now able to solve the issue with plotting the data by using async / await to wait for the promise to resolve... However, now I'm facing the issue with how to stop the setInterval timer that's in a closure.)

I want to accomplish the following:

  • Send 10 fetch requests sequentially and measure response time for each request (in millisec)
  • For each request push response time to an array
  • On click of a start button - starts the plotting of points with a predefined function: drawChart(data) . The points should be added every second.
  • On click of a stop button - stop the plotting.

onLoad event listener:

window.onload = async function () {
   drawChart([]);
   const data = await fetchData(15);
   document.getElementById("start").onclick = () => plotData(data);

   // I want to be able to clearInterval on click of Stop button... but its not working...
   document.getElementById("stop").onclick = clearInterval(plotData);  
};

plot / fetch function:

const plotData = (data) => {
  let i = 0;
  // How do i clear this interval outside of this function?
  const interval = setInterval( () => {
    i++;
    if (i === data.length) { clearInterval(interval); }
    let newData = data.slice(0,i);
    drawChart(newData); 
    console.log('draw');
  }, 1000);
}

const fetchData = async (times) => {
  let url = `https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-1295/lounging-dog.jpg`;
  const data = [];
  for (let i = 0; i < times; i++) {
    start = (new Date()).getTime();
    await fetch(url)
      .then( res => {
        end = (new Date()).getTime();
        console.log('times', i+1);
        console.log('response milisec', end - start);            
        data.push({ xVal: i+1, yVal: end-start}); 
      })
      .catch( e => console.log(e));   
  }
  return data;
};

What I can't wrap my mind about is how to clearInterval in the window context when the setInterval is defined within a callback.

You can also see my CodePen for more information.

Thanks in advance!

To wait for a promise to resolve use await

// get fetch call data
const data = await fetchData(10).then( (res) => {
  console.log(res);
});

// assign button onClick handler, data undefined
document.getElementById("start").onclick = drawChart(data);  

A better way to do this is, instead of waiting for each promise in fetchData to resolve before starting the next fetch, is to create each promise and then await all of them. It would look something like this:

 const fetchData = async (times) => { const url = 'https://reqres.in/api/users?page=2' const promises = []; for (let i = 0; i < times; i++) { start = (new Date()).getTime(); promises.push( fetch(url) .then( res => { end = (new Date()).getTime(); console.log('times', i+1); console.log('response milisec', end - start); return { xVal: i+1, yVal: end-start}; }) .catch( e => console.log(e)) ); } let data = await Promise.all(promises); console.log(data) return data; }; fetchData(3); 

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