1 of 26

Asynchronous TypeScript

Ketan Mayer-Patel

UNC Department of Computer Science

COMP 426: Modern Web Programming (Fall 2026)

Module 1: Fundamentals

Lecture 06

2 of 26

Announcements

  • A02: Pixel Art Maker is out

​

  • Midterm 01 is Monday, September 14th
    • Today’s lecture is the last content to be covered on the exam!��No, I don't know what the format of the midterm will be yet.

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall ‘26)

M1: Fundamentals

L06

!

3 of 26

  • Resources are not limited to files – we can request data too.

Recap: Client and Server Interactions

  • This module, you have learned about how our browser loads websites by requesting website resources (HTML, CSS, JS) from the server.
    • Resources may also include other files, such as images on the site.

​

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall ‘26)

M1: Fundamentals

L06

Requests resource A

Responds w/ resource A

Server

Client

4 of 26

API Endpoints

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall ‘26)

  • We can request data from certain servers by making a request to a certain route.
    • This route is known as an API endpoint.
      • API (Application Programming Interface): Entry point for communication between different software systems.

M1: Fundamentals

L06

5 of 26

API Endpoints

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

  • We can request data from certain servers by making a request to a certain route.
    • This route is known as an API endpoint.
      • API (Application Programming Interface): Entry point for communication between different software systems.
  • Let’s make a request!� �curl https://comp426-apis.vercel.app/api/cs-organizations �
  • We can enter this URL into our browser or use the system utility curl .

M1: Fundamentals

L06

6 of 26

  • Often, data is returned from servers in JavaScript Object Notation (JSON).
  • JSON specifies data in a key-value pair format.
  • JSON makes it easy to retrieve data from servers and represent the data as objects in our JavaScript / TypeScript code…
    • But it is language agnostic too - meaning you can load JSON data into apps written in other programming languages!�
  • So, how do we go about loading data from an API endpoint in our TypeScript code?

JSON

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

M1: Fundamentals

L06

7 of 26

Fetching Data from a Server

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

  • To fetch data from a server, we can use the built-in fetch function.
  • But wait! Not so fast.
    • We cannot just run the following…

M1: Fundamentals

L06

const data = fetch(url).json();

8 of 26

  • JavaScript / TypeScript is single-threaded.
    • This means there is only one call stack.
    • Therefore, only one operation can be performed at a time.
  • Fetching data from APIs require connecting to the internet, requesting data, then retrieving it.
    • This can take a while – especially dependent on factors like internet connection speed and the size of the response data!

Fetching Data from a Server

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

M1: Fundamentals

L06

9 of 26

HTTP and APIs

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

Output:

Start

M1: Fundamentals

L06

script.ts

​

console.log(“Start”);�const data = fetch(`url`).json();

console.log(data);

console.log(“End”);

​

​

This can take a (really) long time!

Remember TS is single-threaded

Our program is blocked from doing anything else while this runs!

10 of 26

  • If execution is blocked, nothing else can happen on the page.
    • This even includes moving the mouse… The entire page freezes 🥶.
  • This is obviously very bad.
    • We need a way to prevent “blocking” operations from blocking the single thread.
    • Asynchronous programming! ✨

​

Motivations for Async Programming

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

M1: Fundamentals

L06

11 of 26

  • What if we:
  • Start an expensive process and leave it to the browser to work on in the background.
  • Continue executing code.
  • When the expensive process is finished, we perform an action with its result.

​

Solution: Asynchronous Event Model

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

M1: Fundamentals

L06

12 of 26

Asynchronous Programming With Callbacks

  • Callbacks are functions that are provided to a blocking (i.e., asynchronous) operation to be called after the operation is done.
    • Event handlers for UI elements are a sort of callback.
    • Registered with addEventListener.
    • Called in the future when event occurs.
  • Original XHR mechanism took this approach.
    • Create XHR object.
    • Configure it with details of HTTP request.
      • Set HTTP method and URL
      • Set up request headers,.
    • Attach callbacks to handle result.
    • Initiate request.
      • This returns immediately.
      • When request is completed in the future, callback is executed.

​

13 of 26

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

Promises

script.ts

fetch("http://some/api/endpoint")

.then((result) => {� // Handle case when a value is

// successfully produced.

return fetch(http://some/other/endpoint);

})

.then((result) => {

// Handle case when a value is

// successfully produced.

})

.catch((error) => {� // Handle case where an error occurs

// along the way.

console.error(error);� })�

​

​

M1: Fundamentals

L06

  • Alternative to callbacks.

​

  • Asynchronous / blocking operations return a promise object.

​

  • Promise objects have methods for specifying what to be done after promise is fulfilled or handling errors.

​

  • Promise objects can be chained if then handler returns another promise.

​

  • This is what fetch() does.

​

14 of 26

async / await

  • Makes writing and reading asynchronous code much, much easier.
  • await can be use with any function that returns a Promise object.
    • Effectively blocks your code from continuing until Promise is resolved.
    • Result of await is resolved value from Promise.
  • Because await is blocking, any function that uses await must be marked as "async"
    • Marking a function as async converts that function into one that returns a Promise.

​

15 of 26

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

With a partner or small group:

​

​

Discuss for ~1-2 minutes - what do you think the output of this script be?

M1: Fundamentals

L06

script.ts

console.log(“Start”);

​

// Mark the “expensive” operation

// with async so that the program

// knows to kick this off and move

// on (handle the result later).

// This prevents blocking!!

const performExpOp = async () => {

await expensiveOperation();

return "I love COMP 426!";

}

​

// Kick off the expensive operation.

const result = performExpOp();

​

​

// Continue running while we wait.�console.log(“End”);

console.log(result);

16 of 26

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

Output:

Start

End

Promise { <pending> }

M1: Fundamentals

L06

script.ts

console.log(“Start”);

​

// Mark the “expensive” operation

// with async so that the program

// knows to kick this off and move

// on (handle the result later).

// This prevents blocking!!

const performExpOp = async () => {

await expensiveOperation();

return "I love COMP 426!";

}

​

// Kick off the expensive operation.

const result = performExpOp();

​

​

// Continue running while we wait.�console.log(“End”);

console.log(result);

Not �“I love COMP 426!”

17 of 26

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

M1: Fundamentals

L06

script.ts

console.log(“Start”)

Execution Sequence

performExpOp() �is called.

Async process kicked off

Async Process

console.log(“End”)

Async process completes and returns

Some time later...

console.log(“Start”);

​

// Mark the “expensive” operation

// with async so that the program

// knows to kick this off and move

// on (handle the result later).

// This prevents blocking!!

const performExpOp = async () => {

await expensiveOperation();

return "I love COMP 426!";

}

​

// Kick off the expensive operation.

const result = performExpOp();

​

​

// Continue running while we wait.�console.log(“End”);

console.log(result);

console.log(result)

The result’s intended value is not found until here.

We can only do something with the intended value after it is found.

18 of 26

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

M1: Fundamentals

L06

script.ts

console.log(“Start”)

Execution Sequence

performExpOp() �is called.

Async process kicked off

Async Process

console.log(“End”)

Async process completes and returns

Some time later...

Promise<T> objects have a then method that takes in a function of type (result: T) => void as a parameter.

Once the asynchronous process completes, the Promise calls this function and passes in the result as the parameter!

This allows us to do something with the result of an asynchronous function.

console.log(“Start”);

​

// Mark the “expensive” operation

// with async so that the program

// knows to kick this off and move

// on (handle the result later).

// This prevents blocking!!

const performExpOp = async () => {

await expensiveOperation();

return "I love COMP 426!";

}

​

// Kick off the expensive operation.

performExpOp()

.then((result) => {

console.log(result);

});

​

// Continue running while we wait.�console.log(“End”);

​

19 of 26

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

M1: Fundamentals

L06

script.ts

console.log(“Start”)

Execution Sequence

performExpOp() �is called.

Async process kicked off

Async Process

console.log(“End”)

Async process completes and returns

The function passed into then is called.

console.log(result)

Some time later...

console.log(“Start”);

​

// Mark the “expensive” operation

// with async so that the program

// knows to kick this off and move

// on (handle the result later).

// This prevents blocking!!

const performExpOp = async () => {

await expensiveOperation();

return "I love COMP 426!";

}

​

// Kick off the expensive operation.

performExpOp()

.then((result) => {

console.log(result);

});

​

// Continue running while we wait.�console.log(“End”);

​

i.e., the passed in function is not added to the call stack until after the async process completes.

20 of 26

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

Output:

Start

End

I love COMP 426!

M1: Fundamentals

L06

script.ts

console.log(“Start”)

Execution Sequence

performExpOp() �is called.

Async process kicked off

Async Process

console.log(“End”)

Async process completes and returns

The function passed into then is called.

console.log(result)

Some time later...

console.log(“Start”);

​

// Mark the “expensive” operation

// with async so that the program

// knows to kick this off and move

// on (handle the result later).

// This prevents blocking!!

const performExpOp = async () => {

await expensiveOperation();

return "I love COMP 426!";

}

​

// Kick off the expensive operation.

performExpOp()

.then((result) => {

console.log(result);

});

​

// Continue running while we wait.�console.log(“End”);

​

i.e., the passed in function is not added to the call stack until after the async process completes.

21 of 26

With a partner or small group:

What should the output of this code be?

Let’s spend ~2-3 minutes on this!

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

Practice

script.ts

const cat = async () => {� await // Action takes 500ms to perform.

return ...�}�const dog = async () => {

await // Action takes 100ms to perform.

return ...

}

​

console.log(“One”);�

cat()� .then(result => { console.log(“Cat”) });

​

console.log(“Two”);

​

dog()� .then(result => { console.log(“Dog”) });

​

console.log(“Three”);

​

​

M1: Fundamentals

L06

22 of 26

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

M1: Fundamentals

L06

script.ts

const cat = async () => {� await // Action takes 500ms to perform.

return ...�}�const dog = async () => {

await // Action takes 100ms to perform.

return ...

}

​

console.log(“One”);

​

cat()� .then((result) => {console.log(“Cat”)});

​

console.log(“Two”);

​

dog()� .then((result) => {console.log(“Dog”)});

​

console.log(“Three”);

​

23 of 26

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

Attendance Question!

What should the output of this code be?

  • When you are done, complete the L06 Attendance assignment on GradeScope

script.ts

const foo = async () => {� await // Action runs for 100ms

return async () => {

return await // Action runs for 300ms

}�}

const bar = async () => {

return await // Action runs for 200ms�}

​

bar().then(_=> { console.log(“bar returned!”); })

​

foo().then(result => {� result().then(_ => {� console.log(“BOO!”);� })� console.log(“foo returned!”);�})

​

M1: Fundamentals

L06

!

24 of 26

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

M1: Fundamentals

L06

script.ts

const foo = async () => {� await // Action runs for 100ms

return async () => {

await // Action runs for 300ms and returns� }�}

const bar = async () => {

await // Action runs for 200ms and returns�}

​

bar().then(_=> { console.log(“bar returned!”); })

​

foo().then(res => {� res().then(_ => {� console.log(“BOO!”);� })� console.log(“foo returned!”);�})

​

​

25 of 26

Recall: Fetching Data from a Server

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

  • To fetch data from a server, we can use the built-in fetch function.
  • This is an asynchronous function → Returns a promise!
  • Note: On the result of the fetch call, you must also call .json(), which is an async function too.

const result = await fetch(...);

const json = await result.json(...);

M1: Fundamentals

L06

26 of 26

With a partner or small group:

  • Your task is to make a web app that displays the name of CS organizations!
  • The starter code is on StackBlitz:
  • Let’s spend 10 minutes on this!
  • Hints:
    • const div = document.createElement(‘div’);
    • div.append(p);

Your Turn!

Asynchronous TypeScript

COMP 426: Modern Web Programming (Fall '26)

M1: Fundamentals

L06