Lesson 16-HTML5 Communication Methods and Applications

HTML5 provides a variety of communication methods, allowing web applications in browsers to achieve effective communication between pages, windows, and even with external services. These communication methods greatly improve the interactivity and complexity of web applications, laying the foundation for building modern, rich client web applications. The following are the main communication methods and their applications in HTML5:

5 communication methods:

  1. postMessage API
  2. WebSockets
  3. Server-Sent Events (SSE)
  4. Fetch API / XMLHttpRequest (XHR)
  5. Web Workers & Service Workers

postMessage API

Introduction

postMessage is a cross-document messaging mechanism introduced by HTML5, which allows scripts from different sources (including same-origin and cross-origin) to exchange data asynchronously and securely in two directions. It can be used to solve communication problems between different windows (such as iframes, pop-up windows, and cross-domain windows).

Usage:

  • The sender sends a message to the receiver by calling otherWindow.postMessage(message, targetOrigin), where message is the data to be passed (usually a string or a serialized JSON object), and targetOrigin is the origin of the window expected to receive the message (can be an exact URL or a wildcard * to limit the scope of message sending to ensure security).
  • The receiver receives the message by listening to the message event (such as window.addEventListener('message', handleMessage)), and checks the source and content of the message in the callback function (such as handleMessage) and handles it accordingly.

Sender:

// Assume that you want to send a JSON object to the parent window
var messageData = { type: 'update', content: 'Some data' };

// Send to the parent window
parent.postMessage(messageData, '*'); // '*' means that any source can receive, and more precise control should be used in actual applications

Receiver:

// Add message event listener
window.addEventListener('message', function(event) {
// Check if the source of the message is credible
if (event.origin !== 'https://trusted-origin.com') return; // Replace with the actual trusted source

var data = event.data;

if (data.type === 'update') {
console.log('Received update:', data.content);
// Perform corresponding processing according to the data content
}
});

Applications:

  • Cross-domain communication: realize the interaction between third-party embedding (such as social media sharing buttons, ads, comment boxes, etc.) and the host page.
  • Communication between iframe content and parent window: in single-page applications (SPA), state synchronization and event notification between iframe embedded sub-applications and the main application.
  • Cross-window communication: communication between pop-up windows, new windows and original windows, such as opening a login window and receiving messages after successful login.

WebSockets

Introduction

WebSockets is a protocol for full-duplex communication on a single TCP connection, providing a persistent, bidirectional, low-latency communication channel. It enables real-time, bidirectional data exchange between clients and servers.

Usage:

  • The client creates a WebSocket instance through new WebSocket(url) and specifies the URL of the server.
  • Use methods and events such as .open, .close, .send, .addEventListener('message') to handle connection establishment, closing, sending messages, and receiving messages.

Client (browser):

// Create a WebSocket instance
var socket = new WebSocket('ws://your-websocket-server.com/ws');

// Callback after connection establishment
socket.addEventListener('open', function(event) {
    console.log('WebSocket connected');
});

// Callback after receiving a message
socket.addEventListener('message', function(event) {
    var data = JSON.parse(event.data); // Assume that the server sends data in JSON format
    console.log('Received:', data);
    // Perform corresponding processing based on the data
});

// Send a message
socket.send(JSON.stringify({ type: 'hello', message: 'Hello from client!' }));

Server (Node.js + ws library as an example):

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
console.log('New WebSocket connection');
ws.on('message', message => {
    const data = JSON.parse(message);
    console.log(`Received: ${data.message}`);

    // Assume a simple confirmation message
    ws.send(JSON.stringify({ type: 'ack', message: 'Acknowledged' }));
    });
});

Applications:

  • Real-time chat application: real-time text, voice, and video chat between users.
  • Stock trading application: real-time push of market data and trading information.
  • Games: real-time state synchronization and player interaction in multiplayer online games.
  • Real-time monitoring system: push and update of real-time data in dashboards and Internet of Things (IoT) applications.

Server-Sent Events (SSE)

Introduction

SSE is a lightweight technology for pushing data from a server to a client. The client creates an EventSource object to connect to the SSE endpoint provided by the server, and the server continuously sends data updates through HTTP responses.

Usage:

  • The client uses new EventSource(url) to create an EventSource object and connect to the server’s SSE endpoint.
  • Receive messages pushed by the server by listening to the message event (such as eventSource.addEventListener('message', handleEvent)).
  • The server sends data in SSE format by setting the appropriate HTTP response header (such as Content-Type: text/event-stream).

Client (browser):

var source = new EventSource('/sse-endpoint');

source.addEventListener('message', function(event) {
    var data = JSON.parse(event.data); // Assume that the server sends data in JSON format
    console.log('Received SSE update:', data);
    // Perform corresponding processing according to the data
});

source.onerror = function(error) {
console.error('Error occurred with SSE:', error);
};

Server (Node.js + Express as an example):

const express = require('express');
const app = express();

app.get('/sse-endpoint', function(req, res) {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  setInterval(() => {
    res.write(`data: {"type": "update", "content": "Some data"}\n\n`);
  }, 5000); // Send updates every 5 seconds

  req.on('close', () => {
    console.log('Client disconnected');
    res.end();
  });
});

app.listen(3000, () => console.log('SSE server listening on port 3000'));

Applications:

News feeds, social network notification updates: real-time push of new articles, comments, likes, etc.
Information applications: real-time weather forecasts, traffic conditions, sports score updates.

Fetch API / XMLHttpRequest (XHR)

Introduction

Although not a dedicated communication method, the Fetch API (and traditional XHR) are standard means of implementing asynchronous data exchange between clients and servers. They are mainly used to initiate HTTP requests to obtain or submit data.

Usage:

  • Fetch API uses fetch(url, options) to initiate a request and returns a Promise, which can further process the response data.
  • XHR uses new XMLHttpRequest() to create an instance, set properties such as request method and URL, call .open() and .send() methods to initiate a request, and handle the response through .onreadystatechange event or .addEventListener(‘load’).
fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => {
    console.log('Fetched data:', data);
    // Process accordingly
})
.catch(error => console.error('Error fetching data:', error));

Application:

  • RESTful API data interaction: get, update, delete resources.
  • AJAX data loading: dynamically load page content to achieve page updates without refresh.

Web Workers & Service Workers

Introduction

Although these two technologies are not directly used for page-to-page communication, they provide the ability to execute scripts in background threads, indirectly supporting efficient communication of Web applications.

  • Web Workers: Allows complex calculations or data processing to be performed in independent background threads, avoiding blocking the main thread and improving application response speed. The main thread and Worker communicate through message passing (postMessage).
  • Service Workers: As a network proxy, it can intercept, cache, and process network requests in the background to achieve offline access, push notifications, background synchronization and other functions. Service Workers communicate with pages through message passing (postMessage).

Web Workers

main.js

// Create a Web Worker
const worker = new Worker('worker.js');

// When the user clicks the button, send the calculation task to the Worker
document.getElementById('calculateButton').addEventListener('click', function() {
    const n = parseInt(document.getElementById('inputNumber').value, 10);
    worker.postMessage({ task: 'fibonacci', value: n }); // Send calculation task
});

// Receive the result returned by the Worker
worker.addEventListener('message', function(event) {
    document.getElementById('result').textContent = `Fibonacci(${event.data.n}): ${event.data.result}`;
});

// Listen for Worker errors
worker.addEventListener('error', function(error) {
    console.error('Worker error:', error);
});

worker.js:

// Define a function to calculate the Fibonacci sequence in Worker
function fibonacci(n) {
    if (n <= 1) return n;
        return fibonacci(n - 1) + fibonacci(n - 2);
    }

// Listen for messages sent by the main thread
self.addEventListener('message', function(event) {
    const data = event.data;

    if (data.task === 'fibonacci') {
        const result = fibonacci(data.value); // Execute calculation tasks
        self.postMessage({ n: data.value, result: result }); // Return the result to the main thread
    }
});

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Web Worker Example</title>
</head>
<body>
  <label for="inputNumber">Enter a number:</label>
  <input type="number" id="inputNumber" value="30">
  <button id="calculateButton">Calculate Fibonacci</button>
  <p id="result"></p>

  <script src="main.js"></script>
</body>
</html>

Service Workers

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Service Worker Example</title>
  <script>
    if ('serviceWorker' in navigator) {
      window.addEventListener('load', function() {
        navigator.serviceWorker.register('sw.js')
          .then(registration => {
            console.log('Service Worker registered:', registration);
          })
          .catch(error => {
            console.error('Service Worker registration failed:', error);
          });
      });
    } else {
      console.log('Service Worker is not supported in this browser.');
    }
  </script>
</head>
<body>
  <!-- Your page content here -->
  <h1>Hello, Service Worker!</h1>
  <img src="/images/example.jpg" alt="Example image">
  <script src="/scripts/main.js"></script>
</body>
</html>

sw.js(Service Worker File):

// Defines a list of resources to cache
const cacheName = 'example-cache-v1';
const cacheAssets = [
  '/',
  '/index.html',
  '/styles.css',
  '/scripts/main.js',
  '/images/example.jpg',
];

// Installation Phase
self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(cacheName)
      .then(cache => {
        console.log('Caching app shell...');
        return cache.addAll(cacheAssets);
      })
  );
});

// During the activation phase, clear the old version cache
self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys()
      .then(cacheNames => {
        return Promise.all(
          cacheNames.map(cacheName => {
            if (cacheName !== cacheName) {
              return caches.delete(cacheName);
            }
          })
        );
      })
      .then(() => {
        console.log('Service Worker activated.');
      })
  );
});

// Cache strategy: intercept and process network requests
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        // If the requested resource is in the cache, it is returned directly
        if (response) {
          return response;
        }

        // Otherwise, try to fetch from the network and cache the response.
        return fetch(event.request)
          .then(response => {
            // Only cache successful GET request results
            if (!response || response.status !== 200 || event.request.method !== 'GET') {
              return response;
            }

            const clone = response.clone();
            caches.open(cacheName)
              .then(cache => {
                cache.put(event.request, clone);
              });

            return response;
          })
          .catch(() => {
            // The network request failed, trying to return a cached alternative resource (such as `offline.html`) from the cache
            return caches.match('/offline.html');
          });
      })
  );
});

Applications:

  • Computation-intensive tasks: such as big data processing, image processing, audio encoding, etc.
  • Offline applications: cache key resources and provide offline access experience.
  • Push notifications: send real-time updates or marketing information to users.
  • Background data synchronization: automatically update data in the background to keep the application and server status consistent.

HTML5 provides a variety of communication methods to meet the communication needs of Web applications in different scenarios, such as cross-window, cross-domain communication, real-time data push, asynchronous data exchange, etc. Developers can choose appropriate communication technologies or use them in combination according to the specific needs of the application to achieve efficient, secure, and real-time Web application functions.

Share your love