or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

application-lifecycle.mdbuild-configuration.mdcomponent-system.mdevent-channels.mdindex.mdunified-api.mdutilities.md
tile.json

event-channels.mddocs/

Event Channel System

Advanced event communication system for inter-page and inter-component messaging with caching, lifecycle management, and navigation integration.

Capabilities

EventChannel Class

Core class for creating isolated event communication channels between pages and components.

/**
 * Event channel for isolated communication between pages/components
 * @param id - Unique channel identifier
 * @param events - Initial event listeners (optional)
 */
class EventChannel {
  constructor(id: number, events?: Record<string, Function>);
  
  /**
   * Emit event to all listeners
   * @param eventName - Name of the event to emit
   * @param args - Arguments to pass to event listeners
   */
  emit(eventName: string, ...args: any[]): void;
  
  /**
   * Register persistent event listener
   * @param eventName - Name of the event to listen for
   * @param fn - Event handler function
   */
  on(eventName: string, fn: Function): void;
  
  /**
   * Register one-time event listener
   * @param eventName - Name of the event to listen for
   * @param fn - Event handler function (automatically removed after first call)
   */
  once(eventName: string, fn: Function): void;
  
  /**
   * Remove event listener(s)
   * @param eventName - Name of the event
   * @param fn - Specific handler to remove (optional, removes all if not provided)
   */
  off(eventName: string, fn?: Function): void;
}

Usage Examples:

// Create event channel with initial events
const eventChannel = new EventChannel(1, {
  dataUpdate: (data) => {
    console.log('Initial data update handler:', data);
  },
  statusChange: (status) => {
    console.log('Status changed to:', status);
  }
});

// Register additional event listeners
eventChannel.on('userAction', (action, userId) => {
  console.log(`User ${userId} performed action: ${action}`);
  updateUserActivity(userId, action);
});

// Register one-time listener
eventChannel.once('initialization', () => {
  console.log('Channel initialized - this runs only once');
  performInitialSetup();
});

// Emit events
eventChannel.emit('userAction', 'login', 12345);
eventChannel.emit('dataUpdate', { timestamp: Date.now(), data: {...} });
eventChannel.emit('statusChange', 'active');

// Remove specific listener
const specificHandler = (data) => console.log('Specific handler:', data);
eventChannel.on('dataUpdate', specificHandler);
eventChannel.off('dataUpdate', specificHandler); // Remove only this handler

// Remove all listeners for an event
eventChannel.off('userAction'); // Removes all userAction listeners

Channel Management Functions

Functions for creating, managing, and retrieving event channels.

/**
 * Create and initialize a new event channel
 * @param events - Initial event listeners (optional)
 * @param cache - Whether to cache the channel for later retrieval (default: true)
 * @returns EventChannel instance
 */
function initEventChannel(events?: Record<string, Function>, cache?: boolean): EventChannel;

/**
 * Retrieve and consume a cached event channel
 * @param id - Channel ID to retrieve (optional, returns next available if not provided)
 * @returns EventChannel instance or undefined
 */
function getEventChannel(id?: number): EventChannel | undefined;

Usage Examples:

import { initEventChannel, getEventChannel } from "@dcloudio/uni-mp-qq";

// Create cached event channel
const channel1 = initEventChannel({
  dataReady: (data) => {
    console.log('Data is ready:', data);
  }
}, true); // cache = true (default)

// Create non-cached event channel
const channel2 = initEventChannel({
  tempEvent: (info) => {
    console.log('Temporary event:', info);
  }
}, false); // cache = false

// Retrieve cached channel by ID
const retrievedChannel = getEventChannel(channel1.id);
console.log('Retrieved channel:', retrievedChannel === channel1); // true

// Retrieve next available cached channel (FIFO)
const nextChannel = getEventChannel(); // Returns first available cached channel

// Note: getEventChannel removes the channel from cache after retrieval
const sameChannel = getEventChannel(channel1.id); // Returns undefined (already consumed)

Navigation Integration

Event channels integrate seamlessly with page navigation for communication between pages.

/**
 * Navigation with event channel integration
 * Automatically handled by uni.navigateTo when events are provided
 */
interface NavigationWithEvents {
  /** Event channel is created automatically and passed in result */
  eventChannel: EventChannel;
}

Usage Examples:

// Page A - Navigate to Page B with event communication
const navigationResult = await uni.navigateTo({
  url: '/pages/detail/detail?id=123',
  events: {
    // Events that Page B can emit back to Page A
    dataUpdate: (updatedData) => {
      console.log('Received updated data from detail page:', updatedData);
      this.updateLocalData(updatedData);
    },
    
    actionPerformed: (actionType, result) => {
      console.log(`Detail page performed ${actionType}:`, result);
      this.handleDetailAction(actionType, result);
    },
    
    pageReady: () => {
      console.log('Detail page is ready');
      // Send initial data to detail page
      navigationResult.eventChannel.emit('initialData', {
        userData: this.userData,
        preferences: this.preferences
      });
    }
  }
});

// Send data to Page B
navigationResult.eventChannel.emit('configUpdate', {
  theme: 'dark',
  language: 'en-US'
});

// Page B - Receive and respond to events
export default {
  onLoad(options) {
    // Get event channel passed from Page A
    const eventChannel = this.getOpenerEventChannel();
    
    // Listen for events from Page A
    eventChannel.on('initialData', (data) => {
      console.log('Received initial data from opener:', data);
      this.userData = data.userData;
      this.preferences = data.preferences;
      this.initializeWithData();
    });
    
    eventChannel.on('configUpdate', (config) => {
      console.log('Config updated:', config);
      this.applyConfiguration(config);
    });
    
    // Emit events back to Page A
    eventChannel.emit('pageReady');
    
    // Emit data updates
    setTimeout(() => {
      eventChannel.emit('dataUpdate', {
        newData: 'Updated from detail page',
        timestamp: Date.now()
      });
    }, 2000);
  },
  
  methods: {
    handleUserAction(actionType) {
      const eventChannel = this.getOpenerEventChannel();
      
      // Process action
      const result = this.processAction(actionType);
      
      // Notify opener page
      eventChannel.emit('actionPerformed', actionType, result);
    }
  }
};

Advanced Event Channel Features

Event Caching

Event channels support automatic event caching when no listeners are present.

// Events emitted before listeners are registered get cached
const channel = initEventChannel();

// Emit event before any listeners are registered
channel.emit('earlyEvent', 'This will be cached');

// Register listener later - cached event will be replayed
channel.on('earlyEvent', (message) => {
  console.log('Received cached event:', message); // "This will be cached"
});

Listener Management

Advanced listener management with type-based behavior.

const channel = initEventChannel();

// Regular listeners persist until manually removed
channel.on('persistentEvent', () => {
  console.log('This listener persists');
});

// One-time listeners are automatically removed after first execution
channel.once('oneTimeEvent', () => {
  console.log('This runs only once');
});

// Emit events multiple times
channel.emit('persistentEvent'); // Listener runs
channel.emit('persistentEvent'); // Listener runs again

channel.emit('oneTimeEvent');     // Listener runs and is removed
channel.emit('oneTimeEvent');     // Nothing happens (listener removed)

Channel Lifecycle

Event channels have a managed lifecycle tied to page navigation.

// Channel creation during navigation
uni.navigateTo({
  url: '/pages/target/target',
  events: {
    // Initial events create the channel
    ready: () => console.log('Target ready')
  }
}).then(result => {
  // Channel is available in navigation result
  const channel = result.eventChannel;
  
  // Channel remains active during page lifetime
  channel.emit('initData', initialData);
});

// In target page
export default {
  data() {
    return {
      eventChannel: null
    };
  },
  
  onLoad() {
    // Retrieve channel created during navigation
    this.eventChannel = this.getOpenerEventChannel();
    
    // Channel is automatically cleaned up when page is destroyed
  },
  
  onUnload() {
    // Channel cleanup happens automatically
    // No manual cleanup required
  }
};

Multi-Channel Communication

Complex applications can use multiple event channels for different purposes.

// Create separate channels for different concerns
const dataChannel = initEventChannel({
  dataUpdate: handleDataUpdate,
  dataError: handleDataError
});

const uiChannel = initEventChannel({
  themeChange: handleThemeChange,
  layoutUpdate: handleLayoutUpdate
});

const analyticsChannel = initEventChannel({
  userAction: trackUserAction,
  pageView: trackPageView
});

// Use channels for specific purposes
dataChannel.emit('dataUpdate', newData);
uiChannel.emit('themeChange', 'dark');
analyticsChannel.emit('userAction', 'button_click');

Event Channel Patterns

Request-Response Pattern

// Requester side
const channel = initEventChannel();

channel.once('response', (data) => {
  console.log('Received response:', data);
});

channel.emit('request', { type: 'getData', params: { id: 123 } });

// Responder side
channel.on('request', (requestData) => {
  const { type, params } = requestData;
  
  if (type === 'getData') {
    const data = fetchData(params.id);
    channel.emit('response', data);
  }
});

Pub-Sub Pattern

// Publisher
const channel = initEventChannel();

setInterval(() => {
  channel.emit('statusUpdate', {
    status: 'active',
    timestamp: Date.now(),
    data: getCurrentStatus()
  });
}, 5000);

// Subscribers
channel.on('statusUpdate', (update) => {
  console.log('Subscriber 1 received:', update);
  updateUI(update);
});

channel.on('statusUpdate', (update) => {
  console.log('Subscriber 2 received:', update);
  logStatusChange(update);
});

State Synchronization Pattern

// State manager
const stateChannel = initEventChannel();
let globalState = { user: null, theme: 'light' };

stateChannel.on('stateChange', (newState) => {
  globalState = { ...globalState, ...newState };
  stateChannel.emit('stateUpdated', globalState);
});

// State consumers
stateChannel.on('stateUpdated', (state) => {
  console.log('State updated:', state);
  updateComponentState(state);
});

// State updaters
stateChannel.emit('stateChange', { theme: 'dark' });
stateChannel.emit('stateChange', { user: { id: 123, name: 'John' } });

Event Channel Architecture

Channel Storage

  • Channels are stored in global maps with unique IDs
  • Cached channels use FIFO retrieval pattern
  • Automatic cleanup prevents memory leaks

Event Processing

  • Events are processed synchronously within channels
  • Cached events are replayed when listeners are added
  • Once-listeners are automatically removed after execution

Navigation Integration

  • Channels are automatically created during navigateTo with events
  • Channel references are passed through navigation results
  • Channels are accessible in target pages via getOpenerEventChannel()

Memory Management

  • Channels are automatically cleaned up when pages are destroyed
  • Event caches are cleared when listeners consume cached events
  • Listener references are properly managed to prevent memory leaks