简体   繁体   中英

JS Class Emit Signal to create chain of events

I've written a larger js class for my vue project designed for mobile. However I need my class to emit a signal so i can chain together other events based on the completion of this class in particular. How can I emit a signal when the property 'hasEnded' is set to True for my class object?

In this case when the user clicks 'Start' as soon as the first timer counts to 100, it should trigger the next one to begin. I want the class to be reusable and i would imagine having it fire an event or signal would be best.

I do not have a huge knowledge of mobile development, so if events are not supported on mobile phones what is the alternative here then?

 class Counter { constructor(name) { this.hasEnded = false; this.value = 0; this.maxValue = 100; this.intervalID = null; this.elementName = '' this.elementName = name; } start() { this.intervalID = setInterval(this.increment.bind(this), 10); } increment() { this.value++ var el = document.querySelector('.' + this.elementName); el.innerHTML = this.value; if (this.value == this.maxValue) { this.hasEnded = true clearInterval(this.intervalID); } } } window.addEventListener('load', function() { let counterA = new Counter('counterA'); let counterB = new Counter('counterB'); /* -- psuedo code -- when counterA.hasFinished == true { counterB.start() } */ var start = document.querySelector('.start'); start.addEventListener('click', function() { counterA.start(); }); })
 <button class="start">Start</button> <br> <label>CounterA:</label> <label class="counterA"></label> <br> <label>CounterB</label> <label class="counterB"></label>

The easiest way to emit as signal is to dispatch an event with EventTarget.dispatchEvent() . The window , document and every HTML element is an extension of this class, so every aforementioned object has this method. This allows you to send a signal which other instances can listen to.

To run your counters sequentially you'll need a system that operates in the form of a list. The list starts at the beginning, index 0 , and continues until there are no more items in that list.

Combine the dispatching of the event and the structure of the list to get this to work. Every time a specific event is fired, move to the next item in the list.

The example below uses these techniques. I've created a new class CounterCollection which will control the list. It listens to a custom event called counterend that is fired every time a counter, you guessed it, has reached the end. It will then go to the next counter in the list and run that one, this goes on until the list runs out. For demonstration' sake, I've added a reset function so you can run it multiple times.

 class CounterCollection { constructor(...counters) { this.counterIndex = 0; this.amountOfCounters = counters.length; this.counters = counters; window.addEventListener('counterend', this.nextCounter.bind(this)); } // Start the counter with the current index. start() { const counter = this.counters[this.counterIndex]; counter.start(); } // Go to the next timer and start it if possible. // Otherwise, reset. nextCounter() { if (this.counterIndex + 1 < this.amountOfCounters) { this.counterIndex++; this.start(); } else { this.counterIndex = 0; this.counters.forEach(counter => { counter.reset(); }); } } } class Counter { constructor(name) { this.hasEnded = false; this.value = 0; this.maxValue = 100; this.intervalID = null; // It's less expensive to store the element here. this.element = document.querySelector('.' + name); } start() { this.intervalID = setInterval(this.increment.bind(this), 10); } increment() { this.value++ this.element.textContent = this.value; if (this.value == this.maxValue) { this.hasEnded = true clearInterval(this.intervalID); // The counter is finished, fire the event. const counterEndEvent = new Event('counterend'); window.dispatchEvent(counterEndEvent); } } // I've added this for the demonstration, so you can run it multiple times. reset() { this.value = 0; this.element.textContent = this.value; } } window.addEventListener('load', function() { let counterA = new Counter('counterA'); let counterB = new Counter('counterB'); // Pass the counters into the collection. const counters = new CounterCollection(counterA, counterB); var start = document.querySelector('.start'); start.addEventListener('click', function() { // Start the collection. counters.start(); }); });
 <button class="start">Start</button> <br> <label>CounterA:</label> <label class="counterA"></label> <br> <label>CounterB</label> <label class="counterB"></label>

Events are part JavaScript and the web. If you are curious if technologies, API's or syntaxes are supported in the browser you're working with, check caniuse.com to see what you can use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM