<button id="start">Start/Stop</button>
<p id="log">Ready</p>
let controller;

const log = msg => {
  document.getElementById("log").textContent = msg;
}

function somethingAsync({signal}){
  if (signal?.aborted){
    return Promise.reject(new DOMException("Aborted", "AbortError"));
  }

  return new Promise((resolve, reject) => {
    log("Promise Started");

    let timeout;

    const abortHandler = () => {
      clearTimeout(timeout);
      reject(new DOMException("Aborted", "AbortError"));
    }

    // start some async operation
    timeout = setTimeout(() => {
      resolve("Promise Resolved");
      signal?.removeEventListener("abort", abortHandler);
    }, 1000);    

    signal?.addEventListener("abort", abortHandler);
  });
}


const startStop = async (e) => {
  e.preventDefault();
  if (!controller){
    controller = new AbortController();
    try{
      const result = await somethingAsync({signal: controller.signal});
      log(result);      
    } 
    catch(e){
      log(e.name === "AbortError" ? "Promise Aborted" : "Promise Rejected")
    }
    finally{
      controller = undefined;
    }
  } else {
    controller.abort();
  }
}

document.getElementById("start").addEventListener("click", startStop);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.