Bab 7: Browser APIs dan Web APIs

Bab 7: Browser APIs dan Web APIs

7.1 Local Storage dan Session Storage

7.1.1 Local Storage

// Storing data
localStorage.setItem('user', JSON.stringify({
    name: 'John',
    age: 30
}));

// Retrieving data
const user = JSON.parse(localStorage.getItem('user'));

// Removing specific item
localStorage.removeItem('user');

// Clearing all data
localStorage.clear();

// Storage event
window.addEventListener('storage', (e) => {
    console.log('Storage changed:', {
        key: e.key,
        oldValue: e.oldValue,
        newValue: e.newValue,
        url: e.url
    });
});

7.1.2 Session Storage

// Storing data
sessionStorage.setItem('cart', JSON.stringify([
    { id: 1, name: 'Product 1' },
    { id: 2, name: 'Product 2' }
]));

// Retrieving data
const cart = JSON.parse(sessionStorage.getItem('cart'));

// Storage management
console.log(sessionStorage.length);
console.log(sessionStorage.key(0));

7.2 Cookies

// Setting cookies
document.cookie = "username=John Doe; expires=Thu, 18 Dec 2024 12:00:00 UTC; path=/";
document.cookie = "language=en; max-age=3600; secure; samesite=strict";

// Reading cookies
function getCookie(name) {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
}

// Deleting cookies
function deleteCookie(name) {
    document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
}

// Cookie utility class
class CookieManager {
    static set(name, value, options = {}) {
        let cookie = `${name}=${value}`;
        
        if (options.expires) {
            cookie += `; expires=${options.expires.toUTCString()}`;
        }
        if (options.path) {
            cookie += `; path=${options.path}`;
        }
        if (options.secure) {
            cookie += '; secure';
        }
        if (options.sameSite) {
            cookie += `; samesite=${options.sameSite}`;
        }
        
        document.cookie = cookie;
    }
    
    static get(name) {
        return getCookie(name);
    }
    
    static delete(name) {
        deleteCookie(name);
    }
}

7.3 Geolocation API

7.3.1 Getting Location

// One-time location request
navigator.geolocation.getCurrentPosition(
    // Success callback
    (position) => {
        console.log('Latitude:', position.coords.latitude);
        console.log('Longitude:', position.coords.longitude);
        console.log('Accuracy:', position.coords.accuracy);
    },
    // Error callback
    (error) => {
        switch(error.code) {
            case error.PERMISSION_DENIED:
                console.error("User denied geolocation permission");
                break;
            case error.POSITION_UNAVAILABLE:
                console.error("Location information unavailable");
                break;
            case error.TIMEOUT:
                console.error("Location request timed out");
                break;
        }
    },
    // Options
    {
        enableHighAccuracy: true,
        timeout: 5000,
        maximumAge: 0
    }
);

// Continuous location tracking
const watchId = navigator.geolocation.watchPosition(
    (position) => {
        updateMap(position.coords);
    },
    (error) => {
        console.error('Error:', error);
    }
);

// Stop tracking
navigator.geolocation.clearWatch(watchId);

7.4 Web Workers

7.4.1 Basic Web Worker

// Main thread (main.js)
const worker = new Worker('worker.js');

worker.postMessage({
    type: 'CALCULATE',
    data: [1, 2, 3, 4, 5]
});

worker.onmessage = (e) => {
    console.log('Result from worker:', e.data);
};

worker.onerror = (error) => {
    console.error('Worker error:', error);
};

// Worker thread (worker.js)
self.onmessage = (e) => {
    if (e.data.type === 'CALCULATE') {
        const result = e.data.data.reduce((sum, num) => sum + num, 0);
        self.postMessage(result);
    }
};

7.4.2 Shared Workers

// Main thread
const sharedWorker = new SharedWorker('shared-worker.js');
sharedWorker.port.start();

sharedWorker.port.onmessage = (e) => {
    console.log('Message from shared worker:', e.data);
};

// Shared worker (shared-worker.js)
const connections = new Set();

self.onconnect = (e) => {
    const port = e.ports[0];
    connections.add(port);
    
    port.onmessage = (e) => {
        // Broadcast to all connections
        connections.forEach(connection => {
            connection.postMessage(e.data);
        });
    };
};

7.5 Service Workers

7.5.1 Service Worker Registration

// Registering a service worker
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js')
        .then(registration => {
            console.log('SW registered:', registration.scope);
        })
        .catch(error => {
            console.error('SW registration failed:', error);
        });
}

// Service worker file (sw.js)
self.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open('v1').then((cache) => {
            return cache.addAll([
                '/',
                '/styles/main.css',
                '/scripts/main.js'
            ]);
        })
    );
});

self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request)
            .then(response => response || fetch(event.request))
    );
});

7.6 Canvas API

7.6.1 Basic Canvas Operations

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

// Drawing shapes
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 100, 100);

// Drawing paths
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(100, 100);
ctx.stroke();

// Drawing text
ctx.font = '24px Arial';
ctx.fillText('Hello Canvas', 10, 50);

// Drawing images
const img = new Image();
img.onload = () => {
    ctx.drawImage(img, 0, 0);
};
img.src = 'image.png';

7.7 WebSocket

7.7.1 WebSocket Connection

const ws = new WebSocket('wss://example.com/socketserver');

ws.onopen = () => {
    console.log('Connected to WebSocket');
    ws.send(JSON.stringify({
        type: 'hello',
        data: 'Hello Server!'
    }));
};

ws.onmessage = (event) => {
    const message = JSON.parse(event.data);
    console.log('Received:', message);
};

ws.onerror = (error) => {
    console.error('WebSocket error:', error);
};

ws.onclose = () => {
    console.log('Disconnected from WebSocket');
};

7.8 Web Audio API

7.8.1 Audio Manipulation

const audioContext = new (window.AudioContext || window.webkitAudioContext)();

// Loading and playing audio
async function playAudio(url) {
    try {
        const response = await fetch(url);
        const arrayBuffer = await response.arrayBuffer();
        const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
        
        const source = audioContext.createBufferSource();
        source.buffer = audioBuffer;
        
        // Adding effects
        const gainNode = audioContext.createGain();
        const pannerNode = audioContext.createStereoPanner();
        
        source.connect(gainNode);
        gainNode.connect(pannerNode);
        pannerNode.connect(audioContext.destination);
        
        source.start(0);
    } catch (error) {
        console.error('Error playing audio:', error);
    }
}

7.9 Praktik dan Latihan

7.9.1 Project: Offline-Capable Web App

// Service Worker Implementation
const CACHE_NAME = 'my-app-v1';
const urlsToCache = [
    '/',
    '/styles/main.css',
    '/scripts/app.js'
];

self.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => cache.addAll(urlsToCache))
    );
});

// Local Storage Implementation
class StorageManager {
    static saveData(key, data) {
        localStorage.setItem(key, JSON.stringify(data));
    }
    
    static getData(key) {
        return JSON.parse(localStorage.getItem(key));
    }
}

7.10 Best Practices

  • Security considerations

  • Performance optimization

  • Error handling

  • Browser compatibility

  • Testing strategies

7.11 Ringkasan

  • Browser storage mechanisms

  • Real-time APIs

  • Background processing

  • Media manipulation

  • Best practices and patterns

7.12 Latihan Akhir Bab

  1. Create an offline-first application

  2. Implement real-time chat using WebSocket

  3. Build a drawing application using Canvas

  4. Create a location-based service

  5. Implement a caching strategy using Service Workers

Last updated