Why Async?

JavaScript runs in a single thread. Talking to an API (fetching scores, logging in) takes time — we can’t block the whole page while we wait. async/await lets us write code that waits for network responses without freezing.

Real API Setup from config.js

The portfolio connects to two backends:

Code Runner Challenge

Practice async/await with a public API. Fetch a joke and parse the JSON response.

View IPYNB Source
// assets/api/config.js
export var pythonURI;
if (location.hostname === 'localhost' || location.hostname === '127.0.0.1') {
    pythonURI = 'http://localhost:8587';
} else {
    pythonURI = 'https://flask.opencodingsociety.com';
}

export var javaURI;
if (location.hostname === 'localhost' || location.hostname === '127.0.0.1') {
    javaURI = 'http://localhost:8585';
} else {
    javaURI = 'https://spring.opencodingsociety.com';
}

export const fetchOptions = {
    method: 'GET',
    mode: 'cors',
    cache: 'default',
    credentials: 'include',
    headers: {
        'Content-Type': 'application/json',
        'X-Origin': 'client'
    },
};
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

POST/GET with Fetch — Login Example

From login.js — this is how the portfolio sends a login request:

Code Runner Challenge

JSON parsing practice. Simulate a leaderboard API response and parse it.

View IPYNB Source
// assets/api/login.js
export function login(options) {
    const requestOptions = {
        ...fetchOptions,                           // spread base options
        method: options.method || 'POST',
        body: options.method === 'POST'
            ? JSON.stringify(options.body)         // serialize JS object → JSON string
            : undefined
    };

    fetch(options.URL, requestOptions)
        .then(response => {
            if (!response.ok) {                    // HTTP error check
                const errorMsg = 'Login error: ' + response.status;
                console.log(errorMsg);
                return;
            }
            options.callback();                    // success callback
        })
        .catch(error => {
            // Network errors (CORS, server down, etc.)
            console.log('Possible CORS or Service Down error: ' + error);
        });
}
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

async/await Pattern — Cleaner Async Code

The same login call rewritten with async/await and JSON parsing:

async function postScore(score, playerName) {
    try {
        const response = await fetch('https://spring.opencodingsociety.com/api/scores', {
            method: 'POST',
            mode: 'cors',
            credentials: 'include',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ score, playerName })   // JS object → JSON
        });

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        const data = await response.json();  // JSON string → JS object
        console.log('Score saved:', data);   // object destructuring possible here
        return data;

    } catch (error) {                        // catches both network & HTTP errors
        console.error('Failed to save score:', error.message);
    }
}
%%js
//CODE_RUNNER: Practice async/await with a public API. Fetch a joke and parse the JSON response.

async function fetchJoke() {
    try {
        console.log('Fetching joke from API...');

        const response = await fetch('https://official-joke-api.appspot.com/random_joke');

        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
        }

        const data = await response.json();   // JSON.parse() equivalent

        // Object destructuring — same technique used when reading leaderboard data
        const { setup, punchline, type } = data;
        console.log(`Type: ${type}`);
        console.log(`Setup: ${setup}`);
        console.log(`Punchline: ${punchline}`);

    } catch (error) {
        console.error('API call failed:', error.message);
    }
}

fetchJoke();

%%js
//CODE_RUNNER: JSON parsing practice. Simulate a leaderboard API response and parse it.

// Simulated API response string (what the server sends back)
const apiResponse = `[
    {"name": "Seonyoo", "score": 2450, "level": 5},
    {"name": "Alice",   "score": 1890, "level": 4},
    {"name": "Bob",     "score": 1230, "level": 3}
]`;

// Parse JSON string into a JavaScript array of objects
const leaderboard = JSON.parse(apiResponse);

console.log('Leaderboard:');
leaderboard.forEach((entry, index) => {
    // Object destructuring
    const { name, score, level } = entry;
    console.log(`#${index + 1} | ${name.padEnd(10)} | Score: ${score} | Level: ${level}`);
});

// Convert back to JSON (for sending to server)
const newEntry = { name: 'You', score: 3000, level: 6 };
leaderboard.push(newEntry);
const updated = JSON.stringify(leaderboard, null, 2);  // pretty-print
console.log('\nUpdated JSON to send back to server:');
console.log(updated);

Summary

Concept Method Example
GET request fetch(url) Load leaderboard scores
POST request fetch(url, { method:'POST', body: JSON.stringify(data) }) Save score
Async/Await async function, await fetch() Clean non-blocking syntax
JSON parsing response.json() / JSON.parse() Convert JSON string ↔ JS object
Error handling try { } catch (error) { } Handle network failures gracefully