or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

attachments.mdbulk-queries.mdchanges-events.mddatabase-operations.mdindex.mdreplication-sync.md

changes-events.mddocs/

0

# Changes & Events

1

2

PouchDB provides comprehensive real-time change monitoring with filtering, live updates, and extensive event handling for both database changes and replication events. The changes feed allows applications to react to database modifications in real-time.

3

4

## Capabilities

5

6

### Changes Feed

7

8

#### db.changes()

9

10

Creates a changes feed to monitor database modifications in real-time.

11

12

```javascript { .api }

13

/**

14

* Listen to database changes

15

* @param options - Changes feed configuration options

16

* @returns Changes object with event emitter interface

17

*/

18

db.changes(options);

19

```

20

21

**Usage Examples:**

22

23

```javascript

24

// Basic changes feed

25

const changes = db.changes();

26

27

changes.on('change', (change) => {

28

console.log('Document changed:', change.id);

29

});

30

31

// Live changes feed

32

const liveChanges = db.changes({

33

live: true,

34

since: 'now',

35

include_docs: true

36

});

37

38

liveChanges.on('change', (change) => {

39

console.log('Live change:', change.doc);

40

});

41

42

// Filtered changes

43

const filteredChanges = db.changes({

44

live: true,

45

filter: (doc) => doc.type === 'user',

46

include_docs: true

47

});

48

```

49

50

### Changes Events

51

52

#### change Event

53

54

Fired when a document is modified in the database.

55

56

```javascript { .api }

57

/**

58

* Change event fired for each document modification

59

* @param change - Change information object

60

*/

61

changes.on('change', (change) => {

62

// change.id: document ID that changed

63

// change.seq: sequence number of the change

64

// change.changes: array of change objects with rev information

65

// change.doc: full document (if include_docs: true)

66

// change.deleted: true if document was deleted

67

});

68

```

69

70

**Change Object Structure:**

71

72

```javascript

73

// Example change object

74

{

75

"id": "user_001",

76

"seq": 123,

77

"changes": [

78

{

79

"rev": "2-abc123def456"

80

}

81

],

82

"doc": {

83

"_id": "user_001",

84

"_rev": "2-abc123def456",

85

"name": "Alice Johnson",

86

"email": "alice.johnson@example.com"

87

}

88

}

89

```

90

91

#### complete Event

92

93

Fired when the changes feed has processed all changes and is complete.

94

95

```javascript { .api }

96

/**

97

* Complete event fired when changes feed finishes

98

* @param info - Completion information

99

*/

100

changes.on('complete', (info) => {

101

// info.results: array of all changes

102

// info.last_seq: final sequence number

103

// info.status: completion status

104

});

105

```

106

107

#### error Event

108

109

Fired when the changes feed encounters an error.

110

111

```javascript { .api }

112

/**

113

* Error event fired when changes feed encounters an error

114

* @param err - Error object

115

*/

116

changes.on('error', (err) => {

117

// err.status: HTTP status code (if applicable)

118

// err.name: error name

119

// err.message: error message

120

});

121

```

122

123

### Changes Control

124

125

#### Canceling Changes Feed

126

127

```javascript { .api }

128

/**

129

* Cancel an active changes feed

130

*/

131

changes.cancel();

132

```

133

134

**Usage Example:**

135

136

```javascript

137

const changes = db.changes({ live: true });

138

139

// Cancel after 30 seconds

140

setTimeout(() => {

141

changes.cancel();

142

console.log('Changes feed canceled');

143

}, 30000);

144

```

145

146

## Event Emitter Interface

147

148

All PouchDB instances inherit from EventEmitter and support standard event handling methods.

149

150

### Event Methods

151

152

#### db.on()

153

154

Adds an event listener for the specified event.

155

156

```javascript { .api }

157

/**

158

* Add event listener

159

* @param event - Event name to listen for

160

* @param handler - Event handler function

161

*/

162

db.on(event, handler);

163

```

164

165

#### db.once()

166

167

Adds a one-time event listener that removes itself after being called once.

168

169

```javascript { .api }

170

/**

171

* Add one-time event listener

172

* @param event - Event name to listen for

173

* @param handler - Event handler function

174

*/

175

db.once(event, handler);

176

```

177

178

#### db.removeListener()

179

180

Removes a specific event listener.

181

182

```javascript { .api }

183

/**

184

* Remove specific event listener

185

* @param event - Event name

186

* @param handler - Event handler function to remove

187

*/

188

db.removeListener(event, handler);

189

```

190

191

#### db.removeAllListeners()

192

193

Removes all event listeners for a specific event or all events.

194

195

```javascript { .api }

196

/**

197

* Remove all event listeners

198

* @param event - Optional event name (removes all if not specified)

199

*/

200

db.removeAllListeners(event);

201

```

202

203

### Database Events

204

205

#### created Event

206

207

Fired when a database is created.

208

209

```javascript { .api }

210

/**

211

* Database created event

212

* @param dbName - Name of the created database

213

*/

214

PouchDB.on('created', (dbName) => {

215

console.log(`Database created: ${dbName}`);

216

});

217

```

218

219

#### destroyed Event

220

221

Fired when a database is destroyed.

222

223

```javascript { .api }

224

/**

225

* Database destroyed event

226

* @param dbName - Name of the destroyed database

227

*/

228

PouchDB.on('destroyed', (dbName) => {

229

console.log(`Database destroyed: ${dbName}`);

230

});

231

```

232

233

#### debug Event

234

235

Fired for debug information when debug mode is enabled.

236

237

```javascript { .api }

238

/**

239

* Debug event fired for debug information

240

* @param info - Debug information array

241

*/

242

PouchDB.on('debug', (info) => {

243

console.log('Debug:', info);

244

});

245

```

246

247

## Configuration Options

248

249

### Changes Options

250

251

```javascript { .api }

252

interface ChangesOptions {

253

/** Enable live/continuous changes feed */

254

live?: boolean;

255

256

/** Start sequence number or 'now' for current */

257

since?: number | string;

258

259

/** Include full document content in changes */

260

include_docs?: boolean;

261

262

/** Include conflicts array in changes */

263

conflicts?: boolean;

264

265

/** Include attachment information */

266

attachments?: boolean;

267

268

/** Return attachments as binary data */

269

binary?: boolean;

270

271

/** Reverse the order of changes */

272

descending?: boolean;

273

274

/** Maximum number of changes to return */

275

limit?: number;

276

277

/** Heartbeat interval for live changes (milliseconds) */

278

heartbeat?: number;

279

280

/** Timeout for changes request (milliseconds) */

281

timeout?: number;

282

283

/** Filter function or design document filter name */

284

filter?: string | ((doc: any, req: any) => boolean);

285

286

/** Specific document IDs to monitor */

287

doc_ids?: string[];

288

289

/** View name for filtered changes */

290

view?: string;

291

292

/** Parameters to pass to filter functions */

293

query_params?: { [key: string]: any };

294

295

/** Include document deletion changes */

296

include_deleted?: boolean;

297

298

/** Style of change results */

299

style?: 'main_only' | 'all_docs';

300

}

301

```

302

303

## Advanced Usage Examples

304

305

### Filtered Changes with Custom Function

306

307

```javascript

308

// Monitor only user documents that are active

309

const userChanges = db.changes({

310

live: true,

311

include_docs: true,

312

filter: (doc) => {

313

return doc.type === 'user' && doc.active === true;

314

}

315

});

316

317

userChanges.on('change', (change) => {

318

console.log('Active user changed:', change.doc.name);

319

});

320

```

321

322

### Changes with Design Document Filter

323

324

```javascript

325

// First, create a design document with a filter function

326

await db.put({

327

_id: '_design/filters',

328

filters: {

329

active_users: function(doc, req) {

330

return doc.type === 'user' && doc.active;

331

}.toString()

332

}

333

});

334

335

// Use the design document filter

336

const changes = db.changes({

337

live: true,

338

filter: 'filters/active_users',

339

include_docs: true

340

});

341

```

342

343

### Monitoring Specific Documents

344

345

```javascript

346

// Monitor changes to specific documents only

347

const specificChanges = db.changes({

348

live: true,

349

doc_ids: ['user_001', 'user_002', 'user_003'],

350

include_docs: true

351

});

352

353

specificChanges.on('change', (change) => {

354

console.log(`Monitored document ${change.id} changed`);

355

});

356

```

357

358

### Changes Feed with Comprehensive Error Handling

359

360

```javascript

361

const changes = db.changes({

362

live: true,

363

since: 'now',

364

include_docs: true,

365

heartbeat: 10000

366

});

367

368

changes.on('change', (change) => {

369

try {

370

// Process the change

371

processDocumentChange(change.doc);

372

} catch (err) {

373

console.error('Error processing change:', err);

374

}

375

});

376

377

changes.on('error', (err) => {

378

console.error('Changes feed error:', err);

379

380

// Restart changes feed after a delay

381

setTimeout(() => {

382

console.log('Restarting changes feed...');

383

startChangesMonitoring();

384

}, 5000);

385

});

386

387

changes.on('complete', (info) => {

388

console.log('Changes feed completed:', info.last_seq);

389

});

390

391

// Function to process document changes

392

function processDocumentChange(doc) {

393

if (doc.type === 'user') {

394

updateUserInterface(doc);

395

} else if (doc.type === 'message') {

396

displayNewMessage(doc);

397

}

398

}

399

```

400

401

### Batch Processing Changes

402

403

```javascript

404

let changeBuffer = [];

405

const BATCH_SIZE = 10;

406

const BATCH_TIMEOUT = 5000;

407

408

const changes = db.changes({

409

live: true,

410

include_docs: true

411

});

412

413

changes.on('change', (change) => {

414

changeBuffer.push(change);

415

416

if (changeBuffer.length >= BATCH_SIZE) {

417

processBatch();

418

}

419

});

420

421

// Process batches periodically

422

setInterval(() => {

423

if (changeBuffer.length > 0) {

424

processBatch();

425

}

426

}, BATCH_TIMEOUT);

427

428

function processBatch() {

429

const batch = changeBuffer.splice(0);

430

console.log(`Processing batch of ${batch.length} changes`);

431

432

// Process all changes in the batch

433

batch.forEach((change) => {

434

// Process individual change

435

console.log(`Processing change for document: ${change.id}`);

436

});

437

}

438

```

439

440

### Changes Feed with Resumption

441

442

```javascript

443

// Store last processed sequence

444

let lastSeq = localStorage.getItem('lastProcessedSeq') || 0;

445

446

function startChangesMonitoring() {

447

const changes = db.changes({

448

live: true,

449

since: lastSeq,

450

include_docs: true

451

});

452

453

changes.on('change', (change) => {

454

// Process the change

455

processChange(change);

456

457

// Update and store last processed sequence

458

lastSeq = change.seq;

459

localStorage.setItem('lastProcessedSeq', lastSeq);

460

});

461

462

changes.on('error', (err) => {

463

console.error('Changes error:', err);

464

// Restart after delay

465

setTimeout(startChangesMonitoring, 5000);

466

});

467

468

return changes;

469

}

470

471

// Start monitoring

472

const changes = startChangesMonitoring();

473

```

474

475

## Performance Considerations

476

477

### Optimizing Changes Feed Performance

478

479

```javascript

480

// High-frequency changes with batching

481

const changes = db.changes({

482

live: true,

483

heartbeat: 30000, // Longer heartbeat interval

484

timeout: 60000, // Longer timeout

485

limit: 100 // Process in batches

486

});

487

488

// Memory-efficient changes monitoring

489

const changes = db.changes({

490

live: true,

491

include_docs: false, // Don't include full docs if not needed

492

since: 'now' // Start from current position

493

});

494

495

// When full documents are needed, fetch them separately

496

changes.on('change', async (change) => {

497

if (shouldProcessDocument(change)) {

498

try {

499

const doc = await db.get(change.id);

500

processDocument(doc);

501

} catch (err) {

502

console.error(`Error fetching document ${change.id}:`, err);

503

}

504

}

505

});

506

```