Monitoring Device Connections with Observables in JavaScript

Vinay Somawat
3 min readJun 6

--

Introduction:

In modern web applications, it’s crucial to have the ability to monitor device connections and disconnections. Whether it’s detecting new cameras, microphones, or speakers being plugged in or unplugged, this information can be valuable for providing users with a seamless and dynamic multimedia experience. In this blog, we will explore how to leverage Observables in JavaScript to create three streams that will notify us whenever a device is connected or disconnected.

Observables and the Event-driven Approach:

Observables are a powerful concept in reactive programming that allows us to treat streams of events as first-class citizens. By utilizing Observables, we can quickly create streams that emit values over time, such as device change events. In our case, we’ll use the RxJS library, which provides a comprehensive set of tools for working with Observables.

The Code:

Let’s dive into the code snippet provided, which demonstrates how to implement Observables for monitoring device connections and disconnections:

// Creating the ioDevices$ Observable
ioDevices$: Observable<Record<MediaDeviceKind, MediaDeviceInfo[]>> = defer(() => {
return fromEvent<Event>(navigator.mediaDevices, 'devicechange')
.pipe(startWith(null))
.pipe(
switchMap(() => defer(() => navigator.mediaDevices.enumerateDevices())),
map((devices) =>
devices.reduce((acc, device) => {
acc[device.kind] = (acc[device.kind] || []).concat(device);
return acc;
}, { audioinput: [], videoinput: [], audiooutput: [] })
)
);
});

// Creating the inputVideoDevices$ Observable
inputVideoDevices$: Observable<MediaDeviceInfo[]> = this.deviceService.ioDevices$.pipe(
map((devices) => devices.videoinput),
distinctUntilChanged((prevDevices, currentDevices) => JSON.stringify(prevDevices) === JSON.stringify(currentDevices))
);

// Creating the inputAudioDevices$ Observable
inputAudioDevices$: Observable<MediaDeviceInfo[]> = this.deviceService.ioDevices$.pipe(
map((devices) => devices.audioinput),
distinctUntilChanged((prevDevices, currentDevices) => JSON.stringify(prevDevices) === JSON.stringify(currentDevices))
);

// Creating the outputAudioDevices$ Observable
outputAudioDevices$: Observable<MediaDeviceInfo[]> = this.deviceService.ioDevices$.pipe(
map((devices) => devices.audiooutput),
distinctUntilChanged((prevDevices, currentDevices) => JSON.stringify(prevDevices) === JSON.stringify(currentDevices))
);

Explanation:

  1. ioDevices$ Observable: This Observable is responsible for emitting values whenever the device list changes due to the 'devicechange' event being triggered. It also emits the initial list of devices when subscribed to. The fromEvent function is used to listen for the 'devicechange' event, and navigator.mediaDevices.enumerateDevices() retrieves the current list of devices. The resulting list is then transformed and reduced to categorize the devices based on their kind (audioinput, videoinput, audiooutput).
  2. inputVideoDevices$, inputAudioDevices$, outputAudioDevices$ Observables: These Observables are derived from the ioDevices$ Observable and focus on specific device categories. They map the respective device arrays (videoinput, audioinput, audiooutput) from the ioDevices$ stream and use distinctUntilChanged to filter out duplicate values. This ensures that only unique device lists are emitted when there are actual changes in the connected devices.

Conclusion:

By harnessing the power of Observables, we have successfully created streams that allow us to monitor device connections and disconnections in real time. With these Observables in place, you can build robust multimedia applications that adapt seamlessly to user device setup changes. The code snippet provided serves as a starting point for implementing device monitoring in your JavaScript projects.

Remember to incorporate error handling and unsubscribe from the Observables when they are no longer needed to optimize resource usage. By continually enhancing user experiences through dynamic device management, you can take your applications to the next level.

Happy coding!

--

--

Vinay Somawat

Software engineer | Frontend

Recommended from Medium

Lists