Communication and Sharing APIs

1. Broadcast Channel API for Tab Communication

Method/Property Description Browser Support
new BroadcastChannel(name) Creates channel with specified name. All same-origin contexts with same name can communicate. All Modern Browsers
channel.postMessage(data) Sends message to all listeners on same channel. Data is cloned using structured clone algorithm. All Modern Browsers
channel.onmessage Event handler for incoming messages. Receives MessageEvent with data property. All Modern Browsers
channel.close() Closes channel and stops receiving messages. Should be called when done to free resources. All Modern Browsers
channel.name Read-only property returning channel name. All Modern Browsers

Example: Tab synchronization with BroadcastChannel

// Create broadcast channel for tab sync
const channel = new BroadcastChannel("app-sync");

// Listen for messages
channel.onmessage = (event) => {
  console.log("Received from another tab:", event.data);
  
  const { "type": type, "payload": payload } = event.data;
  
  switch (type) {
    case "USER_LOGGED_IN":
      updateUIForLoggedInUser(payload.user);
      break;
    case "USER_LOGGED_OUT":
      updateUIForLoggedOutUser();
      break;
    case "CART_UPDATED":
      updateCart(payload.items);
      break;
    case "THEME_CHANGED":
      applyTheme(payload.theme);
      break;
    default:
      console.log("Unknown message type:", type);
  }
};

// Error handling
channel.onerror = (event) => {
  console.error("BroadcastChannel error:", event);
};

// Send message to other tabs
function notifyOtherTabs(type, payload) {
  channel.postMessage({
    "type": type,
    "payload": payload,
    "timestamp": Date.now(),
    "tabId": sessionStorage.getItem("tabId")
  });
}

// Example usage
document.getElementById("loginBtn").addEventListener("click", () => {
  const user = { "id": "123", "name": "John Doe" };
  
  // Update current tab
  updateUIForLoggedInUser(user);
  
  // Notify other tabs
  notifyOtherTabs("USER_LOGGED_IN", { "user": user });
});

// Clean up when page unloads
window.addEventListener("beforeunload", () => {
  channel.close();
});

Example: Real-time notification sync across tabs

// Notification synchronization across tabs
class TabNotificationSync {
  constructor() {
    this.channel = new BroadcastChannel("notifications");
    this.notifications = [];
    
    this.channel.onmessage = this.handleMessage.bind(this);
  }
  
  handleMessage(event) {
    const { "action": action, "notification": notification } = event.data;
    
    switch (action) {
      case "ADD":
        this.addNotification(notification, false); // false = don't broadcast again
        break;
      case "REMOVE":
        this.removeNotification(notification.id, false);
        break;
      case "CLEAR_ALL":
        this.clearAll(false);
        break;
      case "MARK_READ":
        this.markAsRead(notification.id, false);
        break;
    }
  }
  
  addNotification(notification, broadcast = true) {
    this.notifications.push(notification);
    this.updateUI();
    
    if (broadcast) {
      this.channel.postMessage({
        "action": "ADD",
        "notification": notification
      });
    }
  }
  
  removeNotification(id, broadcast = true) {
    this.notifications = this.notifications.filter(n => n.id !== id);
    this.updateUI();
    
    if (broadcast) {
      this.channel.postMessage({
        "action": "REMOVE",
        "notification": { "id": id }
      });
    }
  }
  
  markAsRead(id, broadcast = true) {
    const notification = this.notifications.find(n => n.id === id);
    if (notification) {
      notification.read = true;
      this.updateUI();
      
      if (broadcast) {
        this.channel.postMessage({
          "action": "MARK_READ",
          "notification": { "id": id }
        });
      }
    }
  }
  
  clearAll(broadcast = true) {
    this.notifications = [];
    this.updateUI();
    
    if (broadcast) {
      this.channel.postMessage({ "action": "CLEAR_ALL" });
    }
  }
  
  updateUI() {
    const badge = document.getElementById("notification-badge");
    const unreadCount = this.notifications.filter(n => !n.read).length;
    badge.textContent = unreadCount || "";
    badge.style.display = unreadCount > 0 ? "block" : "none";
  }
  
  destroy() {
    this.channel.close();
  }
}

// Initialize
const notificationSync = new TabNotificationSync();

// Add notification
notificationSync.addNotification({
  "id": Date.now(),
  "message": "New message received",
  "read": false
});
Note: BroadcastChannel enables same-origin tab communication without a server. Messages are not persistent - lost if no tabs listening. Use for real-time sync (login state, cart, settings). Works across tabs, windows, iframes. Data must be structured-cloneable (no functions).

2. Web Share API for Native Sharing

Method/Property Description Browser Support
navigator.canShare(data) Returns boolean indicating if data can be shared. Check before calling share(). Modern Browsers
navigator.share(data) Opens native share dialog. Data object can include title, text, url, files. Modern Browsers
Share Data Property Type Description
title string Title for shared content. Optional.
text string Text/description to share. Optional.
url string URL to share. Optional.
files File[] Array of File objects to share. Optional. Check support with canShare().

Example: Share text and URL

// Check if Web Share API is supported
if (navigator.share) {
  console.log("Web Share API supported");
} else {
  console.log("Web Share API not supported - show fallback UI");
}

// Share content
async function shareContent() {
  // Must be called from user gesture (click, tap)
  const shareData = {
    "title": "Amazing Article",
    "text": "Check out this great article I found!",
    "url": "https://example.com/article/123"
  };
  
  try {
    await navigator.share(shareData);
    console.log("Content shared successfully");
  } catch (error) {
    if (error.name === "AbortError") {
      console.log("User cancelled share");
    } else {
      console.error("Error sharing:", error);
      // Show fallback share options (copy link, social media buttons)
      showFallbackShareUI(shareData);
    }
  }
}

// Add event listener
document.getElementById("shareBtn").addEventListener("click", shareContent);

Example: Share files

// Share image file
async function shareImage() {
  try {
    // Get or create file
    const response = await fetch("/images/photo.jpg");
    const blob = await response.blob();
    const file = new File([blob], "photo.jpg", { "type": "image/jpeg" });
    
    // Check if files can be shared
    const shareData = {
      "files": [file],
      "title": "Beautiful Photo",
      "text": "Check out this photo!"
    };
    
    if (!navigator.canShare) {
      throw new Error("Web Share API not supported");
    }
    
    if (!navigator.canShare(shareData)) {
      throw new Error("Cannot share this file type");
    }
    
    // Share
    await navigator.share(shareData);
    console.log("File shared successfully");
    
  } catch (error) {
    console.error("Error sharing file:", error);
    // Fallback: download file or copy link
    showDownloadOption(file);
  }
}

// Share multiple files
async function shareMultipleFiles(files) {
  const shareData = {
    "files": files,
    "title": "My Files"
  };
  
  if (navigator.canShare && navigator.canShare(shareData)) {
    try {
      await navigator.share(shareData);
      console.log("Files shared");
    } catch (error) {
      console.error("Share failed:", error);
    }
  } else {
    console.log("Cannot share files - browser limitation");
    // Fallback to individual downloads
  }
}

// Share canvas as image
async function shareCanvas(canvas) {
  canvas.toBlob(async (blob) => {
    const file = new File([blob], "drawing.png", { "type": "image/png" });
    
    if (navigator.canShare && navigator.canShare({ "files": [file] })) {
      await navigator.share({
        "files": [file],
        "title": "My Drawing"
      });
    }
  });
}
Note: Web Share API provides native sharing - opens OS share sheet on mobile. Must be triggered by user gesture (click/tap). Only works on HTTPS. Always provide fallback for unsupported browsers. File sharing support varies by platform.
Warning: Always check navigator.share availability before using. Use canShare() to verify data is shareable. User can cancel share - handle AbortError. Desktop browsers have limited support - mobile is primary use case. Provide copy-link fallback.

3. Web Share Target API for Receiving Shares

Manifest Property Description
share_target Defines how app receives shared content. Object with action, method, enctype, params.
share_target.action URL to handle share (e.g., /share). Relative to app scope.
share_target.method HTTP method: "GET" or "POST". Default: "GET".
share_target.enctype For POST: "application/x-www-form-urlencoded" or "multipart/form-data" (for files).
share_target.params Maps share data to query/form parameters: title, text, url, files.

Example: Web app manifest for share target

{
  "name": "My Sharing App",
  "short_name": "ShareApp",
  "start_url": "/",
  "display": "standalone",
  "share_target": {
    "action": "/share",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "title": "title",
      "text": "text",
      "url": "url",
      "files": [
        {
          "name": "media",
          "accept": ["image/*", "video/*", "audio/*"]
        }
      ]
    }
  }
}

Example: Handle shared content in service worker

// service-worker.js - Handle share target
self.addEventListener("fetch", (event) => {
  const url = new URL(event.request.url);
  
  // Check if this is a share request
  if (url.pathname === "/share" && event.request.method === "POST") {
    event.respondWith(handleShare(event.request));
  }
});

async function handleShare(request) {
  try {
    const formData = await request.formData();
    
    const title = formData.get("title") || "";
    const text = formData.get("text") || "";
    const url = formData.get("url") || "";
    const mediaFiles = formData.getAll("media");
    
    // Store shared content
    const shareData = {
      "title": title,
      "text": text,
      "url": url,
      "files": [],
      "timestamp": Date.now()
    };
    
    // Process files
    for (const file of mediaFiles) {
      // Store file (could use IndexedDB, Cache API, etc.)
      const arrayBuffer = await file.arrayBuffer();
      shareData.files.push({
        "name": file.name,
        "type": file.type,
        "size": file.size,
        "data": arrayBuffer
      });
    }
    
    // Store in IndexedDB
    const db = await openDatabase();
    await storeSharedContent(db, shareData);
    
    // Redirect to app with share ID
    const shareId = Date.now();
    return Response.redirect(`/app?share=${shareId}`, 303);
    
  } catch (error) {
    console.error("Error handling share:", error);
    return new Response("Error processing shared content", { "status": 500 });
  }
}

Example: Process shared content in app

// app.js - Process shared content
async function checkForSharedContent() {
  const params = new URLSearchParams(window.location.search);
  const shareId = params.get("share");
  
  if (shareId) {
    try {
      // Retrieve shared content from IndexedDB
      const db = await openDatabase();
      const shareData = await getSharedContent(db, shareId);
      
      if (shareData) {
        console.log("Received shared content:", shareData);
        
        // Display shared content
        if (shareData.title) {
          document.getElementById("title").value = shareData.title;
        }
        if (shareData.text) {
          document.getElementById("content").value = shareData.text;
        }
        if (shareData.url) {
          document.getElementById("link").value = shareData.url;
        }
        if (shareData.files.length > 0) {
          displaySharedFiles(shareData.files);
        }
        
        // Clear URL parameter
        window.history.replaceState({}, "", "/app");
      }
    } catch (error) {
      console.error("Error loading shared content:", error);
    }
  }
}

// Run on page load
checkForSharedContent();
Note: Web Share Target API makes PWAs share targets - appear in OS share sheet. Requires web app manifest with share_target field. App must be installed to appear as share target. Use service worker to handle POST requests with files.
Warning: Only works for installed PWAs - not regular web pages. Limited browser support (mainly Chrome/Edge on Android). Files require POST with multipart/form-data. Test thoroughly on target platforms. Provide clear UI feedback for shared content.

4. MessageChannel and MessagePort APIs

Class/Method Description Browser Support
new MessageChannel() Creates channel with two MessagePort objects for bidirectional communication. All Browsers
channel.port1 First MessagePort of the channel. All Browsers
channel.port2 Second MessagePort of the channel. All Browsers
port.postMessage(data, [transfer]) Sends message through port. Optional transfer array for transferable objects. All Browsers
port.onmessage Event handler for messages. Port must be started via start() or setting onmessage. All Browsers
port.start() Starts port (enables message delivery). Called automatically when setting onmessage. All Browsers
port.close() Closes port and stops message delivery. All Browsers

Example: Communication between iframe and parent

// Parent page
const iframe = document.getElementById("myFrame");

// Create channel
const channel = new MessageChannel();

// Listen on port1
channel.port1.onmessage = (event) => {
  console.log("Parent received:", event.data);
  
  // Send response
  channel.port1.postMessage({
    "type": "RESPONSE",
    "data": "Hello from parent"
  });
};

// Transfer port2 to iframe
iframe.contentWindow.postMessage(
  { "type": "INIT", "message": "Here's your port" },
  "*",
  [channel.port2] // Transfer port ownership
);

// Send message to iframe
setTimeout(() => {
  channel.port1.postMessage({
    "type": "REQUEST",
    "data": "What's your status?"
  });
}, 1000);


// ===== iframe page =====
// Listen for port from parent
window.addEventListener("message", (event) => {
  if (event.data.type === "INIT") {
    // Get transferred port
    const port = event.ports[0];
    
    // Listen on port
    port.onmessage = (e) => {
      console.log("Iframe received:", e.data);
      
      if (e.data.type === "REQUEST") {
        // Send response
        port.postMessage({
          "type": "STATUS",
          "data": "All systems operational"
        });
      }
    };
    
    // Send initial message
    port.postMessage({
      "type": "READY",
      "data": "Iframe initialized"
    });
  }
});

Example: Worker communication with MessageChannel

// Main thread
const worker = new Worker("worker.js");
const channel = new MessageChannel();

// Listen on port1
channel.port1.onmessage = (event) => {
  console.log("Main thread received:", event.data);
  document.getElementById("result").textContent = event.data.result;
};

// Send port2 to worker
worker.postMessage(
  { "type": "INIT_PORT" },
  [channel.port2]
);

// Send work request via channel
function processData(data) {
  channel.port1.postMessage({
    "type": "PROCESS",
    "data": data
  });
}

document.getElementById("processBtn").addEventListener("click", () => {
  processData([1, 2, 3, 4, 5]);
});


// ===== worker.js =====
let port = null;

self.onmessage = (event) => {
  if (event.data.type === "INIT_PORT") {
    // Get transferred port
    port = event.ports[0];
    
    // Listen on port
    port.onmessage = (e) => {
      if (e.data.type === "PROCESS") {
        // Process data
        const result = e.data.data.reduce((sum, num) => sum + num, 0);
        
        // Send result back
        port.postMessage({
          "type": "RESULT",
          "result": result
        });
      }
    };
    
    // Notify ready
    port.postMessage({
      "type": "READY",
      "message": "Worker ready for processing"
    });
  }
};

Example: Dedicated communication channels

// Create multiple channels for different purposes
class ChannelManager {
  constructor() {
    this.channels = new Map();
  }
  
  createChannel(name) {
    const channel = new MessageChannel();
    this.channels.set(name, channel);
    return channel;
  }
  
  getChannel(name) {
    return this.channels.get(name);
  }
  
  sendMessage(channelName, portNumber, data) {
    const channel = this.channels.get(channelName);
    if (channel) {
      const port = portNumber === 1 ? channel.port1 : channel.port2;
      port.postMessage(data);
    }
  }
  
  cleanup() {
    this.channels.forEach(channel => {
      channel.port1.close();
      channel.port2.close();
    });
    this.channels.clear();
  }
}

// Usage
const manager = new ChannelManager();

// Create channels for different modules
const authChannel = manager.createChannel("auth");
const dataChannel = manager.createChannel("data");

// Setup listeners
authChannel.port1.onmessage = (event) => {
  console.log("Auth message:", event.data);
};

dataChannel.port1.onmessage = (event) => {
  console.log("Data message:", event.data);
};

// Transfer ports to worker
worker.postMessage(
  { "type": "SETUP" },
  [authChannel.port2, dataChannel.port2]
);

// Clean up when done
window.addEventListener("beforeunload", () => {
  manager.cleanup();
});
Note: MessageChannel creates dedicated communication pipe with two ports. Use for structured communication between contexts (workers, iframes). Ports are transferable - ownership can be transferred. More efficient than postMessage for ongoing communication.

5. Cross-Origin Communication Patterns

Method Description Use Case
window.postMessage(message, targetOrigin, [transfer]) Sends message to another window/iframe. Always specify targetOrigin for security. Cross-origin iframe communication
window.addEventListener("message", handler) Listens for postMessage events. Always validate event.origin. Receiving cross-origin messages
event.origin Origin of message sender. Validate before processing message. Security check
event.source Reference to window that sent message. Use to send response. Bidirectional communication
event.data Message data (structured clone). Payload
event.ports Array of transferred MessagePort objects. Channel establishment

Example: Secure cross-origin iframe communication

// Parent page (https://parent.com)
const iframe = document.getElementById("childFrame");
const ALLOWED_ORIGIN = "https://child.com";

// Listen for messages from iframe
window.addEventListener("message", (event) => {
  // CRITICAL: Always validate origin
  if (event.origin !== ALLOWED_ORIGIN) {
    console.warn("Message from unauthorized origin:", event.origin);
    return;
  }
  
  console.log("Received from iframe:", event.data);
  
  // Process message
  const { "type": type, "payload": payload } = event.data;
  
  switch (type) {
    case "REQUEST_USER_DATA":
      // Send user data to iframe
      event.source.postMessage({
        "type": "USER_DATA",
        "payload": {
          "userId": "123",
          "name": "John Doe"
        }
      }, ALLOWED_ORIGIN);
      break;
      
    case "HEIGHT_CHANGED":
      // Resize iframe
      iframe.style.height = payload.height + "px";
      break;
      
    default:
      console.log("Unknown message type:", type);
  }
});

// Send message to iframe
function sendToIframe(data) {
  iframe.contentWindow.postMessage(data, ALLOWED_ORIGIN);
}

// Wait for iframe to load
iframe.addEventListener("load", () => {
  sendToIframe({
    "type": "INIT",
    "payload": { "theme": "dark" }
  });
});


// ===== Iframe page (https://child.com) =====
const PARENT_ORIGIN = "https://parent.com";

// Listen for messages from parent
window.addEventListener("message", (event) => {
  // Validate origin
  if (event.origin !== PARENT_ORIGIN) {
    console.warn("Message from unauthorized origin:", event.origin);
    return;
  }
  
  const { "type": type, "payload": payload } = event.data;
  
  switch (type) {
    case "INIT":
      // Initialize with config from parent
      applyTheme(payload.theme);
      
      // Request user data
      window.parent.postMessage({
        "type": "REQUEST_USER_DATA"
      }, PARENT_ORIGIN);
      break;
      
    case "USER_DATA":
      // Use received data
      displayUserInfo(payload);
      break;
  }
});

// Notify parent of height changes
const resizeObserver = new ResizeObserver((entries) => {
  const height = entries[0].contentRect.height;
  window.parent.postMessage({
    "type": "HEIGHT_CHANGED",
    "payload": { "height": height }
  }, PARENT_ORIGIN);
});

resizeObserver.observe(document.body);

Example: Cross-origin authentication flow

// Main app - open OAuth popup
function initiateOAuth() {
  const authWindow = window.open(
    "https://auth-provider.com/oauth",
    "oauth",
    "width=600,height=700"
  );
  
  // Listen for auth result
  const messageHandler = (event) => {
    // Validate origin
    if (event.origin !== "https://auth-provider.com") {
      return;
    }
    
    if (event.data.type === "OAUTH_SUCCESS") {
      console.log("OAuth successful:", event.data.token);
      
      // Store token
      localStorage.setItem("authToken", event.data.token);
      
      // Close popup
      authWindow.close();
      
      // Clean up listener
      window.removeEventListener("message", messageHandler);
      
      // Update UI
      onAuthenticationSuccess(event.data.user);
    } else if (event.data.type === "OAUTH_ERROR") {
      console.error("OAuth failed:", event.data.error);
      authWindow.close();
      window.removeEventListener("message", messageHandler);
      onAuthenticationError(event.data.error);
    }
  };
  
  window.addEventListener("message", messageHandler);
}

// ===== OAuth provider page =====
function completeOAuth(token, user) {
  // Send result to opener
  if (window.opener) {
    window.opener.postMessage({
      "type": "OAUTH_SUCCESS",
      "token": token,
      "user": user
    }, "https://main-app.com"); // Specify target origin
    
    // Close self
    window.close();
  }
}

function failOAuth(error) {
  if (window.opener) {
    window.opener.postMessage({
      "type": "OAUTH_ERROR",
      "error": error
    }, "https://main-app.com");
    
    window.close();
  }
}
Note: postMessage enables secure cross-origin communication. Always specify targetOrigin when sending. Always validate event.origin when receiving. Use structured data with type field. Common for iframes, popups, worker communication.
Warning: NEVER use targetOrigin: "*" with sensitive data - major security risk. Always validate event.origin before processing messages. Don't trust message content - validate and sanitize. Be aware of timing attacks. Use MessageChannel for long-term communication.

6. Channel Messaging API for Worker Communication

Pattern Description Use Case
Worker postMessage Direct message to worker via worker.postMessage(). Simple but limited to one-way request-response. Simple worker tasks
MessageChannel with Workers Create dedicated channel for bidirectional communication. More structured than direct postMessage. Complex worker interactions
SharedWorker Communication Multiple tabs/windows connect to same worker. Each gets own MessagePort. Cross-tab shared state
BroadcastChannel in Worker Workers can use BroadcastChannel to communicate with main thread and other workers. Multi-worker coordination

Example: SharedWorker with MessagePort

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

self.addEventListener("connect", (event) => {
  const port = event.ports[0];
  connections.add(port);
  
  console.log("New connection. Total:", connections.size);
  
  port.addEventListener("message", (e) => {
    const { "type": type, "data": data } = e.data;
    
    switch (type) {
      case "BROADCAST":
        // Send to all connected ports except sender
        connections.forEach(p => {
          if (p !== port) {
            p.postMessage({
              "type": "MESSAGE",
              "data": data
            });
          }
        });
        break;
        
      case "GET_CONNECTION_COUNT":
        port.postMessage({
          "type": "CONNECTION_COUNT",
          "count": connections.size
        });
        break;
    }
  });
  
  port.start();
  
  // Handle disconnect
  port.addEventListener("close", () => {
    connections.delete(port);
    console.log("Connection closed. Remaining:", connections.size);
  });
});


// ===== Main thread usage =====
// Connect to shared worker
const worker = new SharedWorker("shared-worker.js");
const port = worker.port;

port.addEventListener("message", (event) => {
  console.log("Received from shared worker:", event.data);
  
  if (event.data.type === "MESSAGE") {
    displayMessage(event.data.data);
  }
});

port.start();

// Send broadcast message
function broadcastMessage(message) {
  port.postMessage({
    "type": "BROADCAST",
    "data": message
  });
}

// Get connection count
function getConnectionCount() {
  port.postMessage({ "type": "GET_CONNECTION_COUNT" });
}

Example: Multi-worker coordination

// Main thread - coordinate multiple workers
class WorkerPool {
  constructor(scriptUrl, size) {
    this.workers = [];
    this.channels = [];
    this.taskQueue = [];
    this.busyWorkers = new Set();
    
    // Create workers and channels
    for (let i = 0; i < size; i++) {
      const worker = new Worker(scriptUrl);
      const channel = new MessageChannel();
      
      // Setup worker communication
      worker.postMessage(
        { "type": "INIT", "workerId": i },
        [channel.port2]
      );
      
      // Listen on port1
      channel.port1.onmessage = (event) => {
        this.handleWorkerMessage(i, event.data);
      };
      
      this.workers.push(worker);
      this.channels.push(channel);
    }
  }
  
  handleWorkerMessage(workerId, data) {
    if (data.type === "TASK_COMPLETE") {
      console.log(`Worker ${workerId} completed task:`, data.result);
      
      // Mark worker as available
      this.busyWorkers.delete(workerId);
      
      // Process callback
      if (data.taskId && this.callbacks.has(data.taskId)) {
        this.callbacks.get(data.taskId)(data.result);
        this.callbacks.delete(data.taskId);
      }
      
      // Process next task
      this.processNextTask();
    }
  }
  
  async executeTask(taskData) {
    return new Promise((resolve) => {
      const taskId = Date.now() + Math.random();
      
      this.taskQueue.push({
        "id": taskId,
        "data": taskData,
        "callback": resolve
      });
      
      this.callbacks = this.callbacks || new Map();
      this.callbacks.set(taskId, resolve);
      
      this.processNextTask();
    });
  }
  
  processNextTask() {
    if (this.taskQueue.length === 0) return;
    
    // Find available worker
    const availableWorker = this.workers.findIndex(
      (_, index) => !this.busyWorkers.has(index)
    );
    
    if (availableWorker === -1) return; // All busy
    
    const task = this.taskQueue.shift();
    this.busyWorkers.add(availableWorker);
    
    // Send task to worker
    this.channels[availableWorker].port1.postMessage({
      "type": "TASK",
      "taskId": task.id,
      "data": task.data
    });
  }
  
  terminate() {
    this.workers.forEach(worker => worker.terminate());
    this.channels.forEach(channel => {
      channel.port1.close();
    });
  }
}

// Usage
const pool = new WorkerPool("task-worker.js", 4);

// Execute tasks
async function processManyTasks() {
  const tasks = Array.from({ "length": 100 }, (_, i) => ({
    "operation": "calculate",
    "value": i
  }));
  
  const results = await Promise.all(
    tasks.map(task => pool.executeTask(task))
  );
  
  console.log("All tasks completed:", results);
}

processManyTasks();
Note: Use MessageChannel for structured worker communication. SharedWorker enables cross-tab communication via MessagePorts. Each connection gets dedicated port. Good for coordinating work across tabs or managing worker pools.
Warning: SharedWorker has limited browser support (no Safari). Always call port.start() for SharedWorker ports. Clean up ports and workers when done to prevent memory leaks. Test worker communication error scenarios.

Communication and Sharing Best Practices

  • Use BroadcastChannel for simple same-origin tab sync - logout, cart updates
  • Web Share API must be triggered by user gesture - provide fallback
  • Check canShare() before attempting to share files
  • Web Share Target requires installed PWA - test on target platforms
  • MessageChannel more efficient than postMessage for ongoing communication
  • Always validate event.origin in postMessage handlers - critical security
  • Never use targetOrigin: "*" with sensitive data
  • SharedWorker enables cross-tab state but limited browser support
  • Use structured message format with type field for all communication
  • Call port.start() when using addEventListener instead of onmessage
  • Clean up channels, ports, and listeners to prevent memory leaks
  • Provide clear error handling for communication failures