Wayne
Wayne

Reputation: 765

I can't get numbers to console log in ascending order with time delays using promises

I am trying to get the numbers to log in ascending order with various delays. I tried defining the promises separately, but they automatically run which I didn't know was a thing. I then moved on to putting each of the promises into a function and calling .then on them separately, but that also did not work. I have watched multiple videos and can't seem to find one that is using setTimeout the way I am. I have tried everything I can think of and I don't see why I can't get this basic asynchronous code to work.

$('#btn2').click(() => {
  myFuncingFunction();
})

function myFuncingFunction() {
  console.log('1');
  let first = new Promise((resolve, reject) => {

    resolve(setTimeout(() => {
      console.log('2');
    }, 2000));
    if (n === 0) {
      reject();
    }
  }).then(() => {
      let second = new Promise((resolve, reject) => {
        resolve(setTimeout(() => {
          console.log('3');
        }, 1000));

        if (n === 0) {
          reject();
        }
      }).then(() => {
        let third = new Promise((resolve, reject) => {
          setTimeout(() => {
            console.log('Yay')
          }, 3000);
          resolve();

          if (n === 0) {
            reject();
          }
        })
      })
    }
  )
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn2">Go</button>

Upvotes: 0

Views: 79

Answers (1)

StackSlave
StackSlave

Reputation: 10617

I would create a delay function that you can use within an async counter function that you await the delay on at each step of the loop.

function delay(milliseconds = 1000){
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      resolve(milliseconds);
    }, milliseconds);
  });
}
async function counter(start, finish, stepFunc, milliseconds){
  for(let i=start,m=0,d,l=finish+1; i<l; i++){
    d = await delay(milliseconds);
    m += d; stepFunc(i, m);
  }
}
let doc, htm, bod, M, I, S, Q, mobile; // for use on other loads - forget jQuery unless you have an absolute need
addEventListener('load', ()=>{ // M makes an element based on tag - I is document.getElementById
doc = document; htm = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id);
mobile = /Mobi/i.test(nav.userAgent);
S = (selector, within)=>{ // first node based on CSS selector
  let w = within || doc;
  return w.querySelector(selector);
}
Q = (selector, within)=>{ // array based on CSS selector
  let w = within || doc;
  return w.querySelectorAll(selector);
}
/* can put below on another page using a load event */
const btn2 = I('btn2');
btn2.onclick = ()=>{
  counter(1, 20, (increment, milliseconds)=>{
    console.log(increment, milliseconds);
  }, 500).then(()=>{ // 500 milliseconds
    console.log('all done');
  });
}
}); // end load
<button id='btn2'>Go</button>

Note that I would use Date.now() if I was really trying to keep track of time, but this should step how you like.

Upvotes: 1

Related Questions