Asynchronous JavaScript & APIs
                CMM721: Web Application Development - Session 5
                Birmingham Newman University
                Lecturer: James Williams
                Masters Level Conversion Course
                3-hour session • 18 slides • 2 tasks • Live API demos
                
                    Session Timeline:
                    
                        - 10 min: Registration & waiting
 
                        - 20 min: Opening slides
 
                        - 45 min: Task 1
 
                        - 15 min: Break/Catch up
 
                        - 20 min: Secondary slides
 
                        - 45 min: Task 2
 
                        - Remaining: Self-study
 
                    
                 
            
            
                Learning Objectives
                
                    - Understand asynchronous programming concepts
 
                    - Master Promises and async/await syntax
 
                    - Use the Fetch API for HTTP requests
 
                    - Integrate with REST APIs
 
                    - Handle errors in asynchronous code
 
                
            
            
                Synchronous vs Asynchronous
                
                    Synchronous: Code executes line by line, blocking
                
                
                    console.log('First');
                    console.log('Second');
                    console.log('Third');
                    // Output: First, Second, Third
                
                
                    Asynchronous: Non-blocking, allows other code to run
                
                
                    console.log('First');
                    setTimeout(() => console.log('Second'), 1000);
                    console.log('Third');
                    // Output: First, Third, Second (after 1s)
                
            
            
                Callbacks
                Traditional Async Pattern:
                
                    function fetchData(callback) {
                      setTimeout(() => {
                        const data = {name: 'John', age: 30};
                        callback(data);
                      }, 1000);
                    }
                    
                    fetchData((result) => {
                      console.log(result);
                    });
                
                Problem: Callback Hell
                
                    getData(function(a) {
                      getMoreData(a, function(b) {
                        getMoreData(b, function(c) {
                          // Nested callbacks...
                        });
                      });
                    });
                
            
            
                Promises
                
                    Promise: Object representing eventual completion/failure
                
                
                    const promise = new Promise((resolve, reject) => {
                      setTimeout(() => {
                        const success = true;
                        if (success) {
                          resolve({data: 'Success!'});
                        } else {
                          reject(new Error('Failed'));
                        }
                      }, 1000);
                    });
                    
                    promise
                      .then(result => console.log(result))
                      .catch(error => console.error(error));
                
            
            
                🎯 LIVE DEMO: Promise Simulator
                
                    Interactive Promise Example
                    
                    
                    
                    
                        Click a button to see Promises in action!
                    
                 
                
                
            
            
                Async/Await
                
                    async/await: Syntactic sugar for Promises (ES2017)
                
                
                    // Promise approach
                    fetch('https://api.example.com/data')
                      .then(response => response.json())
                      .then(data => console.log(data))
                      .catch(error => console.error(error));
                    
                    // async/await approach
                    async function fetchData() {
                      try {
                        const response = await fetch('https://api.example.com/data');
                        const data = await response.json();
                        console.log(data);
                      } catch (error) {
                        console.error(error);
                      }
                    }
                
            
            
                Fetch API
                Making HTTP Requests:
                
                    // GET request
                    fetch('https://api.github.com/users/github')
                      .then(response => response.json())
                      .then(data => console.log(data));
                    
                    // POST request
                    fetch('https://api.example.com/users', {
                      method: 'POST',
                      headers: {
                        'Content-Type': 'application/json'
                      },
                      body: JSON.stringify({name: 'John', age: 30})
                    })
                      .then(response => response.json())
                      .then(data => console.log(data));
                
            
            
                🎯 LIVE DEMO: Real API Integration
                
                
                
            
            
                Task 1: Weather App with API
                
                    Objective:
                    Build a weather application using the OpenWeather API
                    Requirements:
                    
                        - Create UI with city input and search button
 
                        - Fetch weather data using async/await
 
                        - Display: temperature, weather description, icon
 
                        - Show loading state during fetch
 
                        - Handle errors (invalid city, network issues)
 
                        - Add 5-day forecast display
 
                    
                    API:
                    
                        - OpenWeatherMap API (free tier)
 
                        - Register at openweathermap.org
 
                    
                 
            
            
                Error Handling in Async Code
                
                    async function fetchUserData(userId) {
                      try {
                        const response = await fetch(`/api/users/${userId}`);
                        
                        if (!response.ok) {
                          throw new Error(`HTTP error! status: ${response.status}`);
                        }
                        
                        const data = await response.json();
                        return data;
                      } catch (error) {
                        console.error('Failed to fetch user:', error);
                        throw error; // Re-throw if needed
                      } finally {
                        console.log('Fetch attempt completed');
                      }
                    }
                
            
            
                🎯 LIVE DEMO: Programming Jokes & Facts
                
                    Programming Humor & Knowledge
                    
                    
                    
                        Click a button to fetch programming content!
                    
                 
                
                
            
            
                REST API Concepts
                
                    REST: Representational State Transfer
                
                HTTP Methods (CRUD):
                
                    - GET: Read/retrieve data
 
                    - POST: Create new data
 
                    - PUT: Update/replace data
 
                    - PATCH: Partial update
 
                    - DELETE: Remove data
 
                
                Response Status Codes:
                
                    - 200: OK
 
                    - 201: Created
 
                    - 400: Bad Request
 
                    - 401: Unauthorized
 
                    - 404: Not Found
 
                    - 500: Internal Server Error
 
                
            
            
                Task 2: Todo API Integration
                
                    Objective:
                    Create a todo app using JSONPlaceholder API
                    Requirements:
                    
                        - Fetch todos from: jsonplaceholder.typicode.com/todos
 
                        - Display todos with checkboxes
 
                        - Implement POST to create new todo (simulated)
 
                        - Implement DELETE to remove todo (simulated)
 
                        - Show loading states for all operations
 
                        - Handle all errors gracefully
 
                        - Add filter: all/completed/active
 
                    
                    Bonus:
                    
                        - Add pagination (10 items per page)
 
                        - Implement search functionality
 
                    
                 
            
            
                Parallel Requests
                Promise.all - Wait for all:
                
                    async function fetchMultiple() {
                      try {
                        const [users, posts, comments] = await Promise.all([
                          fetch('/api/users').then(r => r.json()),
                          fetch('/api/posts').then(r => r.json()),
                          fetch('/api/comments').then(r => r.json())
                        ]);
                        return {users, posts, comments};
                      } catch (error) {
                        console.error('One of the requests failed:', error);
                      }
                    }
                
                Promise.race - First to finish:
                
                    const fastest = await Promise.race([
                      fetch('https://api1.example.com'),
                      fetch('https://api2.example.com')
                    ]);
                
            
            
                Best Practices
                
                    - Always handle errors: Use try/catch with async/await
 
                    - Loading states: Show feedback during async operations
 
                    - Timeout handling: Implement request timeouts
 
                    - Avoid callback hell: Use Promises or async/await
 
                    - Cancel requests: Use AbortController for cleanup
 
                    - Cache responses: Avoid redundant API calls
 
                
                
                    Remember: async functions always return a Promise
                
            
            
                Next Session: Django Basics
                
                    - Introduction to Django framework
 
                    - Project and app structure
 
                    - URL routing and views
 
                    - Django templates and template inheritance
 
                    - Static files handling
 
                    - Django settings and configuration
 
                
                Preparation: Install Python 3.11+ and ensure pip is working.
            
            
                Questions & Discussion
                Contact: JWilliams@Staff.newman.ac.uk
                Office Hours: By appointment
                Resources: MDN Fetch API, JavaScript.info
                Thank you for your attention!