The Debounce Plugin debounces event notifications from check-in and check-out operations to optimize performance in high-frequency scenarios like real-time search, rapid user interactions, or auto-save features.
Operations are immediate, notifications are debounced: The plugin executes check-in/check-out operations immediately and updates the registry. Only the event notifications (onCheckIn/onCheckOut hooks) are debounced.
This means your data is always up-to-date, but listeners are notified in batches to reduce processing overhead.
import { useCheckIn } from 'vue-airport';
import { createDebouncePlugin } from '@vue-airport/plugins-base';
const { createDesk } = useCheckIn<SearchResult>();
const { desk } = createDesk('search', {
plugins: [
createDebouncePlugin({
checkInDelay: 500,
checkOutDelay: 300,
maxWait: 2000
})
]
});
checkInDelay: numberDebounce delay in milliseconds for check-in notifications. Default: 300.
createDebouncePlugin({
checkInDelay: 500 // Wait 500ms before notifying
})
checkOutDelay: numberDebounce delay in milliseconds for check-out notifications. Default: 300.
createDebouncePlugin({
checkOutDelay: 300 // Wait 300ms before notifying
})
maxWait: numberMaximum time the notification can be delayed before it's forced to execute. Optional.
createDebouncePlugin({
checkInDelay: 500,
maxWait: 2000 // Force notification after 2 seconds max
})
interface SearchResult {
title: string;
description: string;
}
const { desk } = createDesk('search', {
plugins: [
createDebouncePlugin({
checkInDelay: 500
})
]
});
// Subscribe to debounced check-in events
desk.onDebouncedCheckIn((id, data) => {
console.log('Debounced check-in:', id, data);
// Update UI, trigger API call, etc.
});
// Rapid check-ins (e.g., search results updating)
desk.checkIn('result-1', { title: 'Vue', description: 'Framework' });
desk.checkIn('result-2', { title: 'Vue Router', description: 'Routing' });
desk.checkIn('result-3', { title: 'VueAirport', description: 'State' });
// Registry is updated immediately, but callback is called once after 500ms
// Callback receives all three items (batched)
desk.onDebouncedCheckIn((id, data) => {
console.log('Check-in notification:', id, data.title);
// This is called once after the debounce delay
// with the latest data for each ID
});
desk.onDebouncedCheckOut((id) => {
console.log('Check-out notification:', id);
// This is called once after the debounce delay
// with all the IDs that were checked out
});
Process all pending notifications immediately:
// Queue up some operations
desk.checkIn('item-1', { value: 1 });
desk.checkIn('item-2', { value: 2 });
desk.checkIn('item-3', { value: 3 });
// Don't wait for the delay - flush now
desk.flushDebounce();
// Debounced callbacks are called immediately
Cancel all pending notifications:
// Queue up some operations
desk.checkIn('item-1', { value: 1 });
desk.checkIn('item-2', { value: 2 });
// Changed your mind - cancel the notifications
desk.cancelDebounce();
// Debounced callbacks will NOT be called
// Check how many notifications are pending
console.log(desk.pendingCheckInsCount); // Number of pending check-ins
console.log(desk.pendingCheckOutsCount); // Number of pending check-outs
console.log(desk.hasPendingDebounce); // true if any pending
// Use in UI
const isPending = computed(() => desk.hasPendingDebounce);
<script setup lang="ts">
import { useCheckIn, createDebouncePlugin } from 'vue-airport';
interface SearchResult {
id: string;
title: string;
description: string;
}
const { desk } = createDesk(Symbol('search-results'), {
plugins: [
createDebouncePlugin({
checkInDelay: 300,
maxWait: 1000
})
]
});
const searchQuery = ref('');
const isSearching = computed(() => desk.hasPendingDebounce);
// Subscribe to debounced updates
desk.onDebouncedCheckIn((id, data) => {
console.log('Search result added:', data.title);
// Could trigger additional API calls, analytics, etc.
});
// Simulate rapid search results
watch(searchQuery, async (query) => {
if (!query) {
desk.clear();
return;
}
// Simulate API response with multiple results
const results = await fetchSearchResults(query);
// Clear old results
desk.clear();
// Check in new results (rapid operations)
results.forEach(result => {
desk.checkIn(result.id, result);
});
// Registry is updated immediately
// But debounced callback is called once after delay
});
const displayResults = computed(() => desk.items);
</script>
<template>
<div>
<input
v-model="searchQuery"
placeholder="Search..."
:class="{ searching: isSearching }"
/>
<div v-if="isSearching" class="loading">
Updating results...
</div>
<div class="results">
<div v-for="item in displayResults" :key="item.id">
<h3>{{ item.data.title }}</h3>
<p>{{ item.data.description }}</p>
</div>
</div>
</div>
</template>
<script setup lang="ts">
interface FormData {
title: string;
content: string;
}
const { desk } = createDesk(Symbol('draft'), {
plugins: [
createDebouncePlugin({
checkInDelay: 1000,
maxWait: 5000
})
]
});
const formData = reactive({
title: '',
content: ''
});
// Auto-save on debounced update
desk.onDebouncedCheckIn(async (id, data) => {
console.log('Auto-saving...');
await saveDraft(data);
console.log('Draft saved!');
});
// Update draft on every change
watch(formData, (newData) => {
desk.checkIn('current-draft', { ...newData });
// Saved after 1 second of inactivity, or 5 seconds max
}, { deep: true });
</script>
onDebouncedCheckIn(callback: (id: string | number, data: T) => void): voidSubscribe to debounced check-in notifications.
onDebouncedCheckOut(callback: (id: string | number) => void): voidSubscribe to debounced check-out notifications.
flushDebounce(): voidImmediately process all pending event notifications.
cancelDebounce(): voidCancel all pending event notifications.
pendingCheckInsCount: numberNumber of pending check-in notifications.
pendingCheckOutsCount: numberNumber of pending check-out notifications.
hasPendingDebounce: booleanBoolean indicating if there are any pending notifications.
Multiple operations on the same ID are batched - only the latest data is used:
desk.checkIn('item-1', { value: 1 });
desk.checkIn('item-1', { value: 2 });
desk.checkIn('item-1', { value: 3 });
// After delay, callback is called ONCE with { value: 3 }
When maxWait is set, notifications are forced after the maximum wait time:
const { desk } = createDesk(Symbol('items'), {
plugins: [
createDebouncePlugin({
checkInDelay: 500,
maxWait: 2000
})
]
});
// Operations every 400ms (before 500ms delay)
setInterval(() => {
desk.checkIn('item', { time: Date.now() });
}, 400);
// Notification is forced after 2000ms even though operations continue
Debounce search result updates to avoid excessive rendering:
const { desk } = createDesk(Symbol('search'), {
plugins: [createDebouncePlugin({ checkInDelay: 300 })]
});
// User types rapidly, results update in batches
Debounce save operations while editing:
const { desk } = createDesk(Symbol('document'), {
plugins: [
createDebouncePlugin({
checkInDelay: 1000,
maxWait: 5000
})
]
});
// Save after 1s of inactivity, or 5s max
Debounce notifications for live data feeds:
const { desk } = createDesk(Symbol('live-data'), {
plugins: [
createDebouncePlugin({
checkInDelay: 200,
maxWait: 1000
})
]
});
// Batch rapid updates, ensure UI updates at least every second
Debounce validation checks:
const { desk } = createDesk(Symbol('form-fields'), {
plugins: [createDebouncePlugin({ checkInDelay: 500 })]
});
desk.onDebouncedCheckIn((id, data) => {
validateField(id, data);
});
// 100 operations = 100 API calls
for (let i = 0; i < 100; i++) {
desk.checkIn(`item-${i}`, { value: i });
// Each triggers an API call
}
// 100 operations = 1 batched API call
for (let i = 0; i < 100; i++) {
desk.checkIn(`item-${i}`, { value: i });
}
desk.onDebouncedCheckIn(() => {
// Called once after delay with all items
batchedApiCall(desk.items);
});