or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-framework.mdcommands.mddependency-injection.mdevents-messaging.mdindex.mdkeybindings.mdmenus.mdpreferences-configuration.mdresources-files.mdwidgets-ui.md

events-messaging.mddocs/

0

# Events and Messaging

1

2

Theia's event system provides type-safe event handling with emitters, async event support, cancellation tokens, and disposable subscriptions for building reactive applications.

3

4

## Capabilities

5

6

### Event Interface

7

8

Core event subscription interface for type-safe event handling.

9

10

```typescript { .api }

11

/**

12

* Represents an event that can be subscribed to

13

*/

14

interface Event<T> {

15

/**

16

* Subscribe to the event

17

* @param listener - Function to call when event fires

18

* @param thisArgs - Optional 'this' context for listener

19

* @param disposables - Optional array to add subscription disposable to

20

* @returns Disposable to unsubscribe

21

*/

22

(listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]): Disposable;

23

}

24

```

25

26

### Event Emitter

27

28

Creates and manages events with type safety and subscription management.

29

30

```typescript { .api }

31

/**

32

* Event emitter for firing events to subscribers

33

*/

34

class Emitter<T> {

35

/**

36

* The event that subscribers can listen to

37

*/

38

readonly event: Event<T>;

39

40

/**

41

* Create emitter with optional configuration

42

* @param options - Emitter configuration options

43

*/

44

constructor(options?: EmitterOptions);

45

46

/**

47

* Fire the event to all subscribers

48

* @param event - Event data to send

49

*/

50

fire(event: T): void;

51

52

/**

53

* Process each listener one by one

54

* @param processor - Function that processes each listener, returns false to stop

55

* @returns Promise that resolves when processing is complete

56

*/

57

sequence(processor: (listener: (e: T) => any) => MaybePromise<boolean>): Promise<void>;

58

59

/**

60

* Dispose the emitter and all subscriptions

61

*/

62

dispose(): void;

63

}

64

65

/**

66

* Configuration options for event emitters

67

*/

68

interface EmitterOptions {

69

/** Called when first listener is added */

70

onFirstListenerAdd?: Function;

71

/** Called when last listener is removed */

72

onLastListenerRemove?: Function;

73

/** Threshold for memory leak warnings */

74

leakWarningThreshold?: number;

75

}

76

```

77

78

**Usage Example:**

79

80

```typescript

81

import { Emitter, Event } from "@theia/core";

82

83

class FileWatcher {

84

private readonly onDidChangeEmitter = new Emitter<string>();

85

86

/** Event fired when file changes */

87

readonly onDidChange: Event<string> = this.onDidChangeEmitter.event;

88

89

private watchFile(path: string): void {

90

// File watching logic

91

// When file changes:

92

this.onDidChangeEmitter.fire(path);

93

}

94

95

dispose(): void {

96

this.onDidChangeEmitter.dispose();

97

}

98

}

99

100

// Usage

101

const watcher = new FileWatcher();

102

const subscription = watcher.onDidChange(path => {

103

console.log(`File changed: ${path}`);

104

});

105

106

// Later: subscription.dispose();

107

```

108

109

### Async Event Emitter

110

111

Handles asynchronous event processing with Promise support.

112

113

```typescript { .api }

114

/**

115

* Emitter for async events that return promises

116

*/

117

class AsyncEmitter<T> {

118

readonly event: Event<T>;

119

120

constructor(options?: EmitterOptions);

121

122

/**

123

* Fire async event and wait for all handlers

124

* @param event - Event data

125

* @returns Promise that resolves when all handlers complete

126

*/

127

fireAndAwait(event: T): Promise<void>;

128

129

dispose(): void;

130

}

131

```

132

133

### Queueable Emitter

134

135

Emitter that queues events and fires them in batches.

136

137

```typescript { .api }

138

/**

139

* Emitter that can queue events and fire them as arrays

140

*/

141

class QueueableEmitter<T> extends Emitter<T[]> {

142

/** Current queue of events to fire */

143

currentQueue?: T[];

144

145

constructor(options?: EmitterOptions);

146

147

/**

148

* Queue events to be fired together

149

* @param arg - Events to queue

150

*/

151

queue(...arg: T[]): void;

152

153

/**

154

* Fire all queued events as an array

155

*/

156

fire(): void;

157

158

dispose(): void;

159

}

160

```

161

162

### Wait Until Event

163

164

Special event type for handling async operations with wait semantics.

165

166

```typescript { .api }

167

/**

168

* Event that allows listeners to delay completion

169

*/

170

interface WaitUntilEvent {

171

/**

172

* Register a promise that must complete before event finishes

173

* @param thenable - Promise to wait for

174

*/

175

waitUntil(thenable: Promise<any>): void;

176

}

177

178

namespace WaitUntilEvent {

179

/**

180

* Fire a wait-until event

181

* @param emitter - Event emitter

182

* @param event - Event data

183

* @returns Promise that waits for all waitUntil promises

184

*/

185

function fire<T>(emitter: Emitter<T & WaitUntilEvent>, event: T): Promise<void>;

186

}

187

```

188

189

**Usage Example:**

190

191

```typescript

192

import { Emitter, WaitUntilEvent } from "@theia/core";

193

194

interface BeforeSaveEvent extends WaitUntilEvent {

195

readonly uri: string;

196

}

197

198

class DocumentManager {

199

private readonly onWillSaveEmitter = new Emitter<BeforeSaveEvent>();

200

201

async save(uri: string): Promise<void> {

202

// Fire event and wait for all handlers

203

await WaitUntilEvent.fire(this.onWillSaveEmitter, { uri });

204

205

// Now perform actual save

206

await this.doSave(uri);

207

}

208

209

private async doSave(uri: string): Promise<void> {

210

// Actual save implementation

211

}

212

}

213

214

// Extensions can delay save

215

documentManager.onWillSave(event => {

216

if (event.uri.endsWith('.ts')) {

217

// Format before save

218

event.waitUntil(this.formatTypeScript(event.uri));

219

}

220

});

221

```

222

223

### Cancellation System

224

225

Provides cancellation tokens for long-running operations.

226

227

```typescript { .api }

228

/**

229

* Token that signals when operation should be cancelled

230

*/

231

interface CancellationToken {

232

/** True if cancellation has been requested */

233

readonly isCancellationRequested: boolean;

234

235

/** Event fired when cancellation is requested */

236

readonly onCancellationRequested: Event<any>;

237

}

238

239

/**

240

* Creates cancellation tokens

241

*/

242

class CancellationTokenSource {

243

/** The cancellation token */

244

readonly token: CancellationToken;

245

246

/** Request cancellation */

247

cancel(): void;

248

249

/** Dispose the token source */

250

dispose(): void;

251

}

252

253

/**

254

* Error thrown when operation is cancelled

255

*/

256

class CancellationError extends Error {

257

constructor();

258

}

259

260

/**

261

* Pre-defined tokens

262

*/

263

namespace CancellationToken {

264

/** Token that is never cancelled */

265

const None: CancellationToken;

266

267

/** Token that is already cancelled */

268

const Cancelled: CancellationToken;

269

}

270

```

271

272

**Usage Example:**

273

274

```typescript

275

import { CancellationToken, CancellationTokenSource, CancellationError } from "@theia/core";

276

277

class SearchService {

278

async search(query: string, token: CancellationToken): Promise<string[]> {

279

const results: string[] = [];

280

281

for (let i = 0; i < 1000; i++) {

282

// Check for cancellation

283

if (token.isCancellationRequested) {

284

throw new CancellationError();

285

}

286

287

// Simulate work

288

await this.searchChunk(query, i);

289

results.push(`result-${i}`);

290

}

291

292

return results;

293

}

294

295

private async searchChunk(query: string, chunk: number): Promise<void> {

296

// Simulate async work

297

await new Promise(resolve => setTimeout(resolve, 10));

298

}

299

}

300

301

// Usage with timeout

302

async function searchWithTimeout(service: SearchService, query: string): Promise<string[]> {

303

const source = new CancellationTokenSource();

304

305

// Cancel after 5 seconds

306

setTimeout(() => source.cancel(), 5000);

307

308

try {

309

return await service.search(query, source.token);

310

} finally {

311

source.dispose();

312

}

313

}

314

```

315

316

### Event Utilities

317

318

Utility functions for working with events.

319

320

```typescript { .api }

321

namespace Event {

322

/** Event that never fires */

323

const None: Event<any>;

324

325

/**

326

* Get the maximum number of listeners for an event

327

* @param event - Event to check

328

* @returns Maximum listeners count

329

*/

330

function getMaxListeners(event: Event<unknown>): number;

331

332

/**

333

* Set the maximum number of listeners for an event

334

* @param event - Event to configure

335

* @param maxListeners - Maximum listeners count

336

* @returns The set maximum listeners count

337

*/

338

function setMaxListeners<N extends number>(event: Event<unknown>, maxListeners: N): N;

339

340

/**

341

* Add to the maximum number of listeners for an event

342

* @param event - Event to configure

343

* @param add - Number to add to current max

344

* @returns New maximum listeners count

345

*/

346

function addMaxListeners(event: Event<unknown>, add: number): number;

347

348

/**

349

* Create event that fires only once

350

* @param event - Source event

351

* @returns Event that fires once then disposes

352

*/

353

function once<T>(event: Event<T>): Event<T>;

354

355

/**

356

* Convert event to promise that resolves on first emission

357

* @param event - Source event

358

* @returns Promise that resolves with event data

359

*/

360

function toPromise<T>(event: Event<T>): Promise<T>;

361

362

/**

363

* Transform event data

364

* @param event - Source event

365

* @param map - Transformation function

366

* @returns Event with transformed data

367

*/

368

function map<I, O>(event: Event<I>, map: (i: I) => O): Event<O>;

369

370

/**

371

* Filter event data

372

* @param event - Source event

373

* @param filter - Filter predicate

374

* @returns Event that only fires when filter returns true

375

*/

376

function filter<T>(event: Event<T>, filter: (e: T) => boolean): Event<T>;

377

378

/**

379

* Combine multiple events into single event

380

* @param events - Array of events to combine

381

* @returns Event that fires when any source event fires

382

*/

383

function any<T>(...events: Event<T>[]): Event<T>;

384

function any(...events: Event<any>[]): Event<void>;

385

386

/**

387

* Debounce event firing

388

* @param event - Source event

389

* @param delay - Debounce delay in milliseconds

390

* @returns Debounced event

391

*/

392

function debounce<T>(event: Event<T>, delay: number): Event<T>;

393

}

394

```

395

396

**Usage Example:**

397

398

```typescript

399

import { Event } from "@theia/core";

400

401

class ConfigurationWatcher {

402

private readonly onDidChangeEmitter = new Emitter<string>();

403

404

// Transform and filter events

405

readonly onImportantConfigChange = Event.filter(

406

Event.map(this.onDidChangeEmitter.event, path => path.toLowerCase()),

407

path => path.includes('important')

408

);

409

410

// Debounced events for high-frequency changes

411

readonly onConfigChangeDebounced = Event.debounce(

412

this.onDidChangeEmitter.event,

413

500 // 500ms debounce

414

);

415

}

416

```

417

418

### Message Service

419

420

High-level service for displaying user messages and dialogs.

421

422

```typescript { .api }

423

/**

424

* Service for showing messages to users

425

*/

426

interface MessageService {

427

/**

428

* Show info message

429

* @param message - Message text

430

* @param actions - Optional actions

431

* @returns Promise resolving to selected action

432

*/

433

info(message: string, ...actions: string[]): Promise<string | undefined>;

434

435

/**

436

* Show warning message

437

* @param message - Message text

438

* @param actions - Optional actions

439

* @returns Promise resolving to selected action

440

*/

441

warn(message: string, ...actions: string[]): Promise<string | undefined>;

442

443

/**

444

* Show error message

445

* @param message - Message text

446

* @param actions - Optional actions

447

* @returns Promise resolving to selected action

448

*/

449

error(message: string, ...actions: string[]): Promise<string | undefined>;

450

}

451

452

/**

453

* Service token for MessageService

454

*/

455

const MessageService: symbol;

456

```

457

458

## Types

459

460

```typescript { .api }

461

type EventListener<T> = (e: T) => any;

462

463

type MaybePromise<T> = T | Promise<T>;

464

465

interface Disposable {

466

dispose(): void;

467

}

468

469

interface DisposableCollection extends Disposable {

470

push(disposable: Disposable): Disposable;

471

}

472

```