State Management
The Anyline Web SDK maintains internal state throughout its lifecycle. Understanding state transitions and proper state management is essential for building robust scanning applications.
SDK States
The SDK can be in one of five states at any given time:
enum State {
INITIALIZED = 'initialized',
PAUSED = 'paused',
SCANNING = 'scanning',
STOPPED = 'stopped',
DISPOSED = 'disposed'
}
State Descriptions
- INITIALIZED
-
SDK has been initialized via
init()but scanning has not started yet. Camera is not active. This is the initial state after callinginit(). - SCANNING
-
SDK is actively processing camera frames and scanning for results. Camera stream is active and frames are being processed by the scan engine.
- PAUSED
-
Scanning is temporarily paused. Camera stream remains active but frames are not processed. Can be resumed without reinitializing the camera.
- STOPPED
-
Scanning session has ended. Camera stream may be inactive. Calling
resumeScanning()will restart the camera stream if needed. - DISPOSED
-
SDK has been completely unmounted and cleaned up. All resources are released. Must call
init()again to use the SDK.
Checking Current State
Use the getState() method to check the current SDK state:
import { init, State } from '@anyline/anyline-js';
const anyline = init({ /* ... */ });
// Check current state
const currentState = anyline.getState();
if (currentState === State.SCANNING) {
console.log('Currently scanning');
} else if (currentState === State.INITIALIZED) {
console.log('Ready to start scanning');
}
State Transition Methods
startScanning()
Starts the scanning process and transitions to SCANNING state.
From States: INITIALIZED, STOPPED, PAUSED
Returns: Promise<HTMLVideoElement | undefined> - Returns HTMLVideoElement when called from INITIALIZED state, or undefined when called from PAUSED or STOPPED state
Behavior:
-
From INITIALIZED: Starts camera, loads assets, begins scanning, and returns the video element
-
From STOPPED or PAUSED: Internally calls
resumeScanning()and returnsundefined
const anyline = init({ /* ... */ });
// From INITIALIZED → SCANNING
const video = await anyline.startScanning();
console.log(anyline.getState()); // 'scanning'
console.log(video); // HTMLVideoElement
// From STOPPED → SCANNING
anyline.stopScanning();
await anyline.startScanning(); // Returns undefined, no video element
console.log(anyline.getState()); // 'scanning'
When called from STOPPED or PAUSED state, startScanning() internally calls resumeScanning() and does NOT return the video element. If you need the video element reference, call startScanning() only from INITIALIZED state or use a different approach to access the video element.
|
Calling startScanning() after dispose() rejects with DisposedError. Check the current state (or wrap in a try/catch) before restarting a disposed instance.
|
pauseScanning()
Temporarily pauses frame processing while keeping the camera active.
From States: SCANNING
Behavior:
-
Stops processing frames
-
Camera stream remains active
-
Can be resumed quickly without camera reinitialization
// From SCANNING → PAUSED
anyline.pauseScanning();
console.log(anyline.getState()); // 'paused'
Calling pauseScanning() from any state other than SCANNING has no effect and logs a debug message.
|
stopScanning()
Stops the scanning session.
From States: SCANNING, PAUSED
Behavior:
-
Stops frame processing
-
Camera stream may be stopped (implementation detail)
-
Requires camera restart on resume
// From SCANNING → STOPPED
anyline.stopScanning();
console.log(anyline.getState()); // 'stopped'
Calling stopScanning() from any state other than SCANNING or PAUSED has no effect and logs a debug message.
|
resumeScanning()
Resumes scanning after pause or stop.
From States: PAUSED, STOPPED
Returns: Promise<void>
Behavior:
-
From PAUSED: Immediately resumes frame processing
-
From STOPPED: Restarts camera stream if needed, then resumes
// From PAUSED → SCANNING
await anyline.resumeScanning();
console.log(anyline.getState()); // 'scanning'
// From STOPPED → SCANNING (restarts camera)
await anyline.resumeScanning();
console.log(anyline.getState()); // 'scanning'
Calling resumeScanning() when already in SCANNING state has no effect and logs a debug message.
|
dispose()
Completely unmounts the SDK and cleans up all resources.
From States: Any state
Behavior:
-
Stops scanning if currently in SCANNING state
-
Terminates worker thread
-
Closes camera stream
-
Clears memory
-
Unmounts UI components
-
Transitions to DISPOSED
// From any state → DISPOSED
anyline.dispose();
console.log(anyline.getState()); // 'disposed'
// Must create new instance to use again
const newAnyline = init({ /* ... */ });
Always call dispose() when done with the SDK to prevent memory leaks. This is especially important in single-page applications.
|
Calling dispose() when already DISPOSED will still attempt cleanup operations but is safe to call.
|
Best Practices
-
Always Check State Before Transitions
Check
getState()before calling state transition methods to avoid no-op calls. -
Handle Component Unmounting
Always call
dispose()when your component unmounts to prevent memory leaks. -
Choose Pause vs Stop Wisely
Use
pauseScanning()for temporary interruptions,stopScanning()for longer breaks. -
Listen to Visibility Changes
Implement visibility change handlers to automatically manage scanning state.
-
Handle Disposed State
Check for DISPOSED state and reinitialize if needed. Once disposed, the instance cannot be reused.
-
Use State in UI
Display current state in your UI to give users feedback about scanning status.
-
Avoid Redundant Calls
The SDK silently ignores invalid state transitions (e.g., calling
pauseScanning()when not scanning), but checking state first is more efficient.
Troubleshooting
State Not Changing After Method Call
Problem: Called a state transition method but state didn’t change.
Possible Causes:
-
Called from invalid state (e.g.,
pauseScanning()when not in SCANNING) -
Method threw an error that was not caught
-
Async method not awaited
Solution:
// Check current state
console.log('Before:', anyline.getState());
try {
await anyline.startScanning();
console.log('After:', anyline.getState());
} catch (error) {
console.error('Failed:', error);
}
Cannot Resume After Stop
Problem: resumeScanning() doesn’t work after calling stopScanning().
Solution: resumeScanning() works from both STOPPED and PAUSED states. If it’s not working, check for errors:
anyline.stopScanning();
console.log(anyline.getState()); // Should be 'stopped'
try {
await anyline.resumeScanning();
console.log(anyline.getState()); // Should be 'scanning'
} catch (error) {
console.error('Resume failed:', error);
}
Memory Leaks in SPA
Problem: Application slows down after navigating between pages multiple times.
Solution: Always dispose SDK instances when components unmount:
// Track all instances and dispose them
const instances = [];
function createScanner() {
const anyline = init({ /* ... */ });
instances.push(anyline);
return anyline;
}
// On app shutdown or route change
function cleanup() {
instances.forEach(instance => {
if (instance.getState() !== State.DISPOSED) {
instance.dispose();
}
});
instances.length = 0;
}
See Also
-
API Reference - Complete API reference
-
Plugin Configuration - Configuration options
-
Error Handling - Error handling patterns
-
General Examples - Code examples and framework integration
-
Getting Started - Getting started guide