Skip to main content
Mobile Launcher
Learning & TutorialsWeb Basics

Async JavaScript

Mastering Promises and Async/Await in React Native

Async JavaScript in React Native

Mobile apps are inherently asynchronous. Network requests, reading files, getting location, or waiting for user interaction all take time.

In mobileLauncherStandard, we handle this using Promises and Async/Await.

The Old Way vs The New Way

❌ Callbacks (Do not use)

Javascript
getData(function(a) {
    getMoreData(a, function(b) {
        // Callback Hell 
    });
});

✅ Async/Await (Our Standard)

We use async/await for cleaner, readable code that looks synchronous.

Real World Example: Authentication

Let's look at src/features/auth/services/auth.service.ts. This service handles logging users in, which requires talking to Supabase (network request) and saving tokens to device storage (disk I/O).

Typescript
// src/features/auth/services/auth.service.ts

// 1. Mark function as 'async'
async signIn(credentials: LoginCredentials) {
    try {
        // 2. 'await' the network request
        // The code PAUSES here until Supabase responds
        const { data, error } = await supabase.auth.signInWithPassword({
            email: credentials.email,
            password: credentials.password,
        });

        if (error) throw error;

        // 3. 'await' the disk write
        // We pause again to ensure tokens are saved before returning
        await this.saveTokens(tokens);

        return { success: true, user };

    } catch (error) {
        // 4. Handle errors centrally
        logger.error("Sign in error", error);
        return { success: false, error: error.message };
    }
}

Key Concepts

1. The async keyword

Declares that a function returns a Promise. Even if you return true, it actually returns Promise<true>.

2. The await keyword

  • Can only be used inside an async function.
  • It pauses execution until the Promise resolves.
  • It unwraps the Promise result (e.g., const data = await promise).

3. Error Handling (try/catch)

Always wrap async code in try/catch blocks. If a network request fails, it "throws" an error that you must catch, otherwise your app might crash (or leave the user stuck in a loading state).

Common Pitfalls

"Forgetting to await"

Typescript
// ❌ WRONG
const user = supabase.auth.getUser(); 
console.log(user); // Logs: Promise { <pending> }

// ✅ RIGHT
const user = await supabase.auth.getUser();
console.log(user); // Logs: User object

"ForEach with Async"

Array.forEach does NOT wait for promises.

Typescript
// ❌ WRONG - This will not wait!
items.forEach(async (item) => {
    await saveItem(item);
});
console.log('Done'); // Prints "Done" before items are saved

// ✅ RIGHT - Use map + Promise.all
const promises = items.map(item => saveItem(item));
await Promise.all(promises);
console.log('Done');

Interactive Practice

[!TIP] Go to StackBlitz and try writing a function that fetches data from https://jsonplaceholder.typicode.com/todos/1.

Javascript
// Copy this to StackBlitz
async function fetchTodo() {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
    const json = await response.json();
    console.log(json);
  } catch (e) {
    console.error(e);
  }
}

fetchTodo();