Skip to content
JavaScript Browser Web APIs Explained — Geolocation, Notifications, Workers & Observers

JavaScript Browser Web APIs Explained — Geolocation, Notifications, Workers & Observers

DodaTech Updated Jun 15, 2026 8 min read

Browser Web APIs extend JavaScript beyond basic syntax, giving you access to device features, background processing, and browser internals. The Doda Browser uses Web Workers for tab isolation and the Notification API for download alerts. The Durga Antivirus Pro dashboard uses Intersection Observer to lazy-load scan results and Web Workers for background threat analysis.

What You’ll Learn

  • Geolocation API — getting the user’s location
  • Notification API — sending system notifications
  • Web Workers — running code in background threads
  • Service Workers — intercepting network requests
  • Intersection Observer — detecting element visibility
  • Resize Observer — responding to element size changes
  • Clipboard API — reading and writing clipboard data
  • Building a custom notification system

Why Web APIs Matter

Web APIs turn JavaScript from a simple page-scripting language into a platform for building full-featured applications. Without the Geolocation API, Google Maps couldn’t show your location. Without Web Workers, complex spreadsheet apps would freeze during calculations. These APIs bridge the gap between web apps and native apps.

Learning Path

    flowchart LR
  A[JS DOM & Browser APIs] --> B[Browser Storage]
  B --> C[Web APIs]
  C --> D[Performance]
  C --> E[You Are Here]
  
Prerequisites: You should understand JavaScript promises, async/await, and basic DOM manipulation. Some APIs require HTTPS (Geolocation, Notifications).

Geolocation API

Get the user’s current position (requires permission):

function getCurrentPosition() {
  return new Promise((resolve, reject) => {
    if (!navigator.geolocation) {
      reject(new Error('Geolocation not supported'));
      return;
    }

    navigator.geolocation.getCurrentPosition(
      (position) => {
        resolve({
          lat: position.coords.latitude,
          lng: position.coords.longitude,
          accuracy: position.coords.accuracy
        });
      },
      (error) => {
        switch (error.code) {
          case error.PERMISSION_DENIED:
            reject(new Error('User denied location access'));
            break;
          case error.POSITION_UNAVAILABLE:
            reject(new Error('Location unavailable'));
            break;
          case error.TIMEOUT:
            reject(new Error('Location request timed out'));
            break;
        }
      },
      { enableHighAccuracy: true, timeout: 5000, maximumAge: 30000 }
    );
  });
}

// Usage
try {
  const pos = await getCurrentPosition();
  console.log(`Latitude: ${pos.lat}, Longitude: ${pos.lng}`);
} catch (error) {
  console.error('Location error:', error.message);
}

Security note: Geolocation requires HTTPS (except on localhost) and prompts the user for permission. Respect the user’s choice — don’t request location unless your feature genuinely needs it.

Notification API

Send system notifications outside the browser window:

async function showNotification(title, body) {
  // Request permission
  const permission = await Notification.requestPermission();
  if (permission !== 'granted') {
    throw new Error('Notification permission denied');
  }

  // Show notification
  const notification = new Notification(title, {
    body: body,
    icon: '/icon-192.png',
    tag: 'unique-tag',  // Replaces existing notifications with same tag
    vibrate: [200, 100, 200]
  });

  // Handle click
  notification.onclick = () => {
    window.focus();
    notification.close();
  };

  // Auto-close after 10 seconds
  setTimeout(() => notification.close(), 10000);
}

await showNotification('Scan Complete', 'No threats found in 1,247 files');

Web Workers

Run CPU-intensive code in a separate thread without blocking the UI:

// main.js
const worker = new Worker('scanner-worker.js');

worker.postMessage({
  cmd: 'scan',
  files: ['file1.pdf', 'file2.exe', 'file3.jpg']
});

worker.onmessage = (event) => {
  console.log('Scan result:', event.data);
  // Output: Scan result: { threats: 0, scanned: 3 }
};

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

// scanner-worker.js
self.onmessage = (event) => {
  const { cmd, files } = event.data;

  if (cmd === 'scan') {
    // Simulate heavy scanning
    const results = files.map(file => ({
      file,
      threats: Math.floor(Math.random() * 2),
      timestamp: Date.now()
    }));
    self.postMessage({ threats: results.filter(r => r.threats > 0).length, scanned: files.length });
  }
};

Real-world use: The Durga Antivirus Pro web dashboard uses a Web Worker to scan file signatures in the background. The main thread stays responsive so users can browse the UI while scanning runs.

Worker Lifecycle

  • Create: new Worker('script.js')
  • Communicate: postMessage() / onmessage
  • Terminate: worker.terminate() (from main) or self.close() (from worker)
  • Errors: worker.onerror catches uncaught errors in the worker

Service Workers

Service Workers act as a programmable network proxy, enabling offline support, caching, and push notifications:

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

// sw.js — basic offline cache
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open('app-v1').then(cache => {
      return cache.addAll([
        '/',
        '/styles/main.css',
        '/scripts/app.js'
      ]);
    })
  );
});

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

Service Workers only work over HTTPS (or localhost). They’re the foundation of Progressive Web Apps (PWAs).

Intersection Observer

Detect when elements enter or leave the viewport — perfect for lazy loading and infinite scroll:

function observeVisibility(element, callback) {
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        callback(entry.target);
        observer.unobserve(entry.target); // Only fire once
      }
    });
  }, {
    threshold: 0.1,  // 10% visible
    rootMargin: '50px' // Trigger 50px early
  });

  observer.observe(element);
  return () => observer.disconnect();
}

// Lazy load images
document.querySelectorAll('img[data-src]').forEach(img => {
  observeVisibility(img, (el) => {
    el.src = el.dataset.src;
    el.removeAttribute('data-src');
  });
});

Resize Observer

Respond to element size changes (not just window resize):

const box = document.getElementById('responsive-box');

const observer = new ResizeObserver(entries => {
  for (const entry of entries) {
    const { width, height } = entry.contentRect;
    console.log(`Box is now ${width}x${height}`);

    // Adjust layout based on size
    if (width < 300) {
      box.classList.add('compact');
    } else {
      box.classList.remove('compact');
    }
  }
});

observer.observe(box);

Difference from window resize: ResizeObserver watches individual elements, not just the viewport. Use it for responsive components inside a dashboard or editor.

Clipboard API

Read and write clipboard contents securely:

async function copyToClipboard(text) {
  try {
    await navigator.clipboard.writeText(text);
    console.log('Copied:', text);
  } catch (err) {
    console.error('Copy failed:', err);
  }
}

async function readFromClipboard() {
  try {
    const text = await navigator.clipboard.readText();
    return text;
  } catch (err) {
    console.error('Read failed:', err);
    return '';
  }
}

// Copy on click
document.getElementById('copyBtn').addEventListener('click', () => {
  copyToClipboard('Hello from Doda Browser!');
});

Custom Notification System

Combine the Notification API with a Web Worker for persistent alerts:

// notification-manager.js
class NotificationManager {
  constructor(workerScript = 'notification-worker.js') {
    this.worker = new Worker(workerScript);
    this.handlers = new Map();

    this.worker.onmessage = (event) => {
      const { type, data } = event.data;
      const handler = this.handlers.get(type);
      if (handler) handler(data);
    };
  }

  requestPermission() {
    return Notification.requestPermission();
  }

  schedule(title, body, delay) {
    this.worker.postMessage({
      cmd: 'schedule',
      payload: { title, body, delay }
    });
  }

  on(type, handler) {
    this.handlers.set(type, handler);
  }
}

// notification-worker.js
self.onmessage = (event) => {
  const { cmd, payload } = event.data;

  if (cmd === 'schedule') {
    setTimeout(() => {
      self.postMessage({
        type: 'notification',
        data: {
          title: payload.title,
          body: payload.body,
          timestamp: Date.now()
        }
      });
    }, payload.delay);
  }
};

Common Mistakes

1. Using Web APIs without checking support

navigator.geolocation.getCurrentPosition(...) // Crashes if unsupported

Fix: Always check for the API first: if ('geolocation' in navigator).

2. Creating too many Web Workers

Each worker is a separate OS thread. Create workers sparingly and reuse them.

3. Not handling permission denial

const notif = new Notification('Hi'); // Throws if permission denied

Fix: Always check permission or use Notification.requestPermission() first.

4. Service Worker scope confusion

A Service Worker in /scripts/sw.js can only control pages in /scripts/. Fix: Place the worker file at the root level for maximum scope.

5. Not disconnecting observers

const observer = new IntersectionObserver(...);
observer.observe(element);
// Never disconnect — memory leak!

Fix: Call observer.disconnect() when the component is destroyed.

Practice Questions

  1. What’s the difference between Web Workers and Service Workers? Web Workers are for CPU-intensive background tasks. Service Workers act as network proxies for offline support and push notifications.

  2. When would you use Intersection Observer instead of scroll events? Intersection Observer is more performant (runs off the main thread) and easier to use for visibility detection.

  3. Why do some Web APIs require HTTPS? For security — APIs like Geolocation, Notifications, and Service Workers can be abused on insecure connections.

  4. What happens when a Web Worker throws an uncaught error? The worker.onerror event fires in the main thread. The worker stops unless you handle the error.

Challenge: Build a lazy image loader using Intersection Observer that also handles responsive images (srcset).

Mini Project: Background File Scanner

// file-scanner.js
class FileScanner {
  constructor() {
    this.worker = new Worker('scan-worker.js');
    this.results = new Map();
  }

  scan(file) {
    return new Promise((resolve, reject) => {
      const id = crypto.randomUUID();
      this.results.set(id, { resolve, reject });

      this.worker.postMessage({ id, file });

      this.worker.onmessage = (e) => {
        const handler = this.results.get(e.data.id);
        if (handler) {
          handler.resolve(e.data.result);
          this.results.delete(e.data.id);
        }
      };

      this.worker.onerror = (e) => {
        const handler = this.results.get(id);
        if (handler) {
          handler.reject(e);
          this.results.delete(id);
        }
      };
    });
  }
}

// Usage
const scanner = new FileScanner();
const result = await scanner.scan(largeFile);
console.log('Scan result:', result);

FAQ

What is the difference between Web Workers and Service Workers?
Web Workers handle CPU-intensive tasks in a background thread. Service Workers proxy network requests, enabling offline support, push notifications, and background sync.
Do all browsers support these APIs?
Most modern browsers support the Web APIs covered here. Check CanIUse.com for specific API support in your target browsers.
Can Web Workers access the DOM?
No. Workers run in a separate global context with no access to DOM, window, or document. They communicate via postMessage.
What permissions do I need for the Notification API?
You must request permission via Notification.requestPermission(). The user can grant or deny it.
Is the Clipboard API secure?
Yes — reading the clipboard requires user interaction (like a click) and only works with HTTPS. Writing is less restricted.

What’s Next

LessonDescription
JavaScript HomeBack to the JavaScript hub
https://tutorials.dodatech.com/programming-languages/javascript/js-dom/DOM & Browser APIs
https://tutorials.dodatech.com/programming-languages/javascript/js-storage/Browser Storage
https://tutorials.dodatech.com/programming-languages/javascript/js-performance/JavaScript performance optimization
PWAProgressive Web Apps

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

What’s Next

Congratulations on completing this JavaScript Web APIs tutorial! Here’s where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro