Phase 1: Mobile Fundamentals

Asynchronous programming, promises & callbacks

Beginner ~3 min read
Think of it this way A friendly analogy. Read this if the technical version feels dense. Show Hide

Imagine you're playing a really fun game on your tablet. You tap a button to load a new level, or maybe to see your friend's high score. But then, for a few seconds, everything freezes! You can't tap anywhere else, you can't scroll, nothing. It's like the whole game just stopped to think, or to get one big thing done, and wouldn't let you do anything else until it was finished. That's no fun, right? We want our apps to be super quick and always ready for our taps, even when they're busy doing important things behind the scenes.

Now, let's think about going to your favorite restaurant. You tell the waiter what you'd like to eat (that's like your app starting a big task, such as downloading a cool new picture from the internet). If you had to stand right there, watching the kitchen door, until your food was ready, you couldn't do anything else! You couldn't talk to your family, color in your placemat, or even just look around the room. You'd be totally stuck, waiting for just that one thing.

But that's not how it works, is it? Instead, you tell the waiter your order, they take it to the kitchen, and then you go back to doing other things at your table. The waiter doesn't make you wait; they let you keep chatting and looking at the menu while your food is being cooked. This is just like how your app can do "asynchronous" tasks. It starts something big, like downloading a picture, but it doesn't make you freeze and wait. It lets you keep tapping, scrolling, and playing while that other task works quietly in the background.

So, how do you know when your food is finally ready? You don't keep checking the kitchen yourself. Instead, the waiter promises to bring your food to your table when it's done. Or, you gave them a special instruction: "When the food is ready, please bring it to me at table number seven." That instruction, "bring it to me at table number seven," is like a "callback." It's a little message or task you give now, for something that needs to happen later, once the main job (cooking your food) is finished. Your app works the same way: it tells a background task, "Hey, when you're done downloading that image, then show it on the screen!" This means when you build your own apps someday, you'll be able to make them really smooth and fun to use, letting people keep playing or interacting while all the busy behind-the-scenes work gets done.

Imagine your mobile app needs to download an image from the internet. If your app waited synchronously for this image to load, your entire app would freeze until the download is complete – imagine tapping a button and nothing happening for seconds! This is where asynchronous programming comes in. It allows your app to start a long-running task (like downloading data, reading from a database, or performing heavy calculations) in the "background" without blocking the main thread that handles your user interface. Your app remains responsive, allowing users to scroll, tap, and interact while background tasks complete.

So, how do you know when that background task is finished, and how do you get its result? That's where callbacks come in. A callback is simply a function that you pass to another function (the one performing the asynchronous task), with the expectation that the callback function will be executed later, once the asynchronous task has completed. Think of it like ordering food: you place your order (start the async task), and the restaurant promises to "call you back" (execute your callback function) when your food is ready. This is a fundamental pattern for handling asynchronous results.

While callbacks work, they can become cumbersome, especially when you have multiple asynchronous tasks that depend on each other, leading to "callback hell" (deeply nested callbacks). To make asynchronous code cleaner and easier to manage, many modern programming environments introduce Promises. A Promise is an object representing the eventual completion (or failure) of an asynchronous operation and its resulting value. Instead of passing a callback directly, you get a Promise back, which you can then chain with .then() to handle success or .catch() to handle errors. This provides a more structured and readable way to manage complex async workflows.

Key Takeaways

  • Asynchronous programming keeps your mobile app's user interface responsive by performing long tasks in the background.
  • Callbacks are functions executed after an asynchronous operation finishes, delivering its result.
  • Promises offer a more structured and readable way to manage asynchronous operations, improving upon nested callbacks.
  • Understanding these concepts is fundamental for building smooth and responsive mobile applications.

Code Example

javascript
Preview

How this code works

This code demonstrates how to handle operations that take time, like fetching data over a network, without making the entire application freeze. It uses Promise objects to manage the eventual success or failure of such tasks, allowing the rest of the program to continue running concurrently.

The fetchData function creates a new Promise. Inside this promise, setTimeout simulates a 2-second delay, mimicking a slow network request. After this delay, if a simulated success condition is true (as it is currently hardcoded), the resolve function is called with the successful data. If success were false, the reject function would be called to signal an error. One subtle thing to note is that while the reject path is defined, the line const success = true; currently guarantees the promise will always resolve.

When the fetchData() promise is used, console.log("Fetching data...") runs immediately. The .then() method is chained to the promise to specify what should happen once the task successfully resolves, and .catch() handles any errors if the task rejects. Both .then() and .catch() will execute after the 2-second delay. Importantly, the final console.log("App continues to run...") also runs immediately, showcasing that the application does not pause and wait for the data fetch to complete, which is the core benefit of asynchronous programming.