Slow vs immediate cancellation

by winstonchang

HTML

<h3>
Delayed cancellation
</h3>
<button onclick="startCount1()">
Start
</button>

<button onclick="cancel1()">
Cancel
</button>

<div id="output1" style="background-color: #ccc">
Output: 
</div>


<br>


<h3>
Immediate cancellation
</h3>
<button onclick="startCount2()">
Start
</button>

<button onclick="cancel2()">
Cancel
</button>

<div id="output2" style="background-color: #ccc">
Output: 
</div>

TypeScript

// =====================================
// Delayed cancellation
// =====================================
let cancelToken = new CancellationToken()

async function startCount1() {
  const outputEl= document.getElementById("output1")
  for await (const item of slowNumberStream()) {
    if (isCanceled1) {
      outputEl.append("Canceled!");
      break;
    }
    outputEl.append(item);
  }
}

function cancel1() {
  isCanceled1 = true;
}

// =====================================
// Immediate cancellation
// =====================================
let isCanceled2 = false;

async function startCount2() {
  const outputEl= document.getElementById("output2")
  for await (const item of slowNumberStream()) {
    if (isCanceled2) {
      outputEl.append("Canceled!");
      break;
    }
    outputEl.append(item);
  }
}

function cancel2() {
  isCanceled2 = true;
}




// =====================================
// Cancellation token class
// =====================================
class CancellationToken {
  isCancellationRequested = false;
  function onCancellationRequested(fn: ()=>{}) {
  
  },
  function cancel() {
    this.isCancellationRequested = true;
  }
}


// =====================================
// Number stream generator
// =====================================
async function* slowNumberStream(
  n: number = 100,
  delay: number = 2
): AsyncGenerator<string> {
  for (let i = 0; i < n; i++) {
    await new Promise((resolve) => setTimeout(resolve, delay * 1000));
    yield `${i} `;
  }
}