1

I have function slideUp() which called with a click of button, click event calls another async function removeSlideUp() which returns a promise. but clicking on the button multiple times calls the removeSlideUp() immediately, I want all the clicks to que and call removeSlideup() one after other only after 'transitionend' event is complete. I am new to javascript and do not know where I am stuck

here is my code

async function slideUp() {
  await removeSlideUp();
}

function removeSlideUp() {
  return new Promise(function (resolve, reject) {
    //console.log(smartAlert.classList.contains("slideup"));
    if (smartAlert.classList.contains("slideup") === false) {
      smartAlert.classList.add("slideup");
      smartAlert.addEventListener(
        "transitionend",
        function () {
          console.log("completed");
          smartAlert.classList.remove("slideup");
          resolve();
        },
        { once: true }
      );
    } else {
      smartAlert.classList.remove("slideup");
      resolve();
    }
  });
}

$('button[name="btn_show"]').click(function () {
  slideUp();
});

Note: It needs to be done in pure javascript no jquery or other framework I am unable to que the clicks to execute one by one when removeSlideUp is called it does produce desired results

following code allowed to get promises from transitionend event properly. Code promise return code was taken from resolving a promise with EventListener from second approach for answer by @Volune

//lets start playing
const buttonShow = document.getElementById("btn_show");
buttonShow.addEventListener("click", async () => {
  let result;
  switch (smartAlert.classList.contains("slideup")) {
    case true:
      smartAlert.classList.remove("slideup"); //this line triger the transition to happen
      result = await transitoinEnd("Show alert is complete");
      console.log(result);
      break;

    default:
      smartAlert.classList.add("slideup");
      result = await transitoinEnd("Hide alert is complete");
      console.log(result);
      setTimeout(() => {
        smartAlert.classList.remove("slideup");
      }, 1000);
      result = await transitoinEnd("Show alert is complete");
      console.log(result);
  }
});

const buttonHide = document.getElementById("btn_hide");
buttonHide.addEventListener("click", async () => {
  smartAlert.classList.add("slideup"); //this line triger the transition to happen
  const result = await transitoinEnd("Hide alert is complete");
  console.log(result);
});

const smartAlert = document.getElementById("smart-alert");
const transitoinEnd = (message) => {
  return new Promise((resolve) => {
    smartAlert.addEventListener(
      "transitionend",
      (animationendListener = () => {
        smartAlert.removeEventListener(
          "transitionend",
          animationendListener
        );
        //call any handler you want here, if needed
        resolve(message);
      })
    );
  });
};
Zubair Ahmd
  • 208
  • 1
  • 9

1 Answers1

1

I want all the clicks to que and call removeSlideup() one after other*

Well yes, you need a queue then. There is none in your code currently. The simplest way to do it is just a promise chain:

let queue = Promise.resolve();
$('button[name="btn_show"]').click(function () {
  queue = queue.then(slideUp);
});
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I am not sure if this code prevent calling slideUp or removeSlideUp() immediately but clicking multiple times on button make it unusable further and page needs to be refreshed before button click event can be triggered again – Zubair Ahmd Jan 14 '23 at 16:55
  • Are you sure the promise returned by `slideUp` does eventually fulfill? – Bergi Jan 14 '23 at 20:11
  • no I don't know and I don't know how to check that – Zubair Ahmd Jan 14 '23 at 21:24
  • Use a debugger to step through the code. Place a breakpoint on the `resolve()` calls. Are they hit as expected? – Bergi Jan 14 '23 at 22:11
  • Also, easier to verify: Is the `console.log("completed");` executed as expected? – Bergi Jan 14 '23 at 22:12
  • Also, use `let i=0;` and ``queue = queue.then(() => console.log(`start ${i}`)).then(slideUp).then(() => console.log(`end ${i++}`), console.error);`` – Bergi Jan 14 '23 at 22:14
  • finally second approach in answer from @Volune helped me from this question to received promises properly now I'll add que and check https://stackoverflow.com/questions/35718645/resolving-a-promise-with-eventlistener – Zubair Ahmd Jan 14 '23 at 22:18
  • 1
    finally I have achieved desired result, I was making a horrible mistake of declaring queue= Promise.resolve() inside the button click thus reseting the promise resolve with each click. – Zubair Ahmd Jan 16 '23 at 02:07