Jamie Jamie - 3 years ago 164
TypeScript Question

Calling a service using EventListeners

Disclaimer: Title is not super exact.

I have a service with a public method 'openCamera' that calls a library in the global object and attaches eventlisteners to its HTML elements. When I call this service method from the HTML elements events, it works fine, but not when I call it via events attached to the window element. An example below:

class ImageService {
public static AttachEventOnce = false;
public openCamera() {
let camera = new JpegCamera('myContainer');
// captureBtn and videoBox are HTML elements generated from the library once instantiated
camera.captureBtn.addEventListener('click', () => this.openCamera()); // this works fine
camera.videoBox.addEventListener('resize', () => this.openCamera()); // doesn't enter here ie not calling it
if (!ImageService.AttachEventOnce) {
var that = this;
window.addEventListener('resize', () => that.openCamera()); // the buttons stop working
ImageService.AttachEventOnce = true;

The logic have been somewhat minified but more or less the same. I just want to call the service method again and again when window is resized. I don't care where I attach the listener (HTML element generated from the library or window).

My take: The window seem to retain the older object reference too as well as other listerers for other buttons which I think is causing the issue.

Answer Source

The window seem to retain the older object reference too as well as other listerers for other buttons which I think is causing the issue.

Correct — not because it's on window, but because you're using an arrow function and only hooking the event once, on the first instance where openCamera is called. So it doesn't matter whether that instance is discarded by everything else, it's the only instance that will receive that resize event. (There's also no reason for the var that = this; thing and then using that inside the function; arrow functions close over this like they do variables, so it does exactly what just using this within the function would do.)

It's not clear why you're doing that as opposed to hooking the event in an instance-specific way like you are the other events. If you remove the logic hooking it only once, you'll get the per-instance behavior.

Separately: It's odd to be attaching new event handlers every time the event occurs. You'll very quickly have them stacking up. The first time (say) you receive a click, you'll add a second click handler; the next time you receive a click, you'll receive two of them (one for each handler), and add two more handlers; and so on, doubling every time. This is bad enough with clicks, but disasterous with resize as there are a lot of resize events triggered when the window is being resized.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download