Use Backend Service / Web Worker for Metronome?


I’ve built a metronome (the thing, that musicians use to hold the tempo - tick, tack, tick, tack) with Typescript / Angular2 / Nativescript (2.4) using the nativescript-sound plugin.

Unfortunately, the interval (time between the “ticks”) isn’t very consistent. Is there any possibility to fix it? I thought of Backend-Services / Web-Workers… But they can’t access the plugin (to create the tick-sound), right?

let sound = require("nativescript-sound");

export class MetronomeComponent{

        public metronome = sound.create("~/pages/metronome/audio/click.mp3"); // preload the audio file 

        // A button triggers the start()-function
            this.stop(); // stop running ticks if needed
            this.tick(); // start the metronome

        // Is it possible to relocate this function to the backend?
        public tick() {
                this.timer = setTimeout(this.tick.bind(this), 60000/this.interval);

I’d appreciate your help!



There are a couple of different plugins for this it looks like:


I believe the OP meant the Workers, those already present in the NS runtimes.

@tarek, you have complete* access to the underlying native API (and thus plugins that access the native API) in JavaScript even on a Worker thread, you will just have to see/test whether the plugin runs alright on the Worker.


@Pete.K @Nick
Thx for your answers. I tried really hard the last days, to implement the metronome as a worker.
So far, I could successfully play the sound through the plugin and even create a loop.

But I couldn’t find out, how to stop the loop:


            var worker = new Worker('./workers/worker');
            worker.postMessage({ tempo: 120 });
            worker.onmessage = function(msg) {
                if ( {
                console.log("WILL NEVER REACH THIS POINT...");
            } else {


require('globals'); // necessary to bootstrap tns modules on the new thread
var soundNs = require("nativescript-sound");
var metronome = soundNs.create("~/pages/metronome/audio/click.mp3");

onmessage = function(msg) {
    var request =;
    var tempo = request.tempo;

    var result = timeout(tempo);

    var msg = result !== undefined ? { success: true, src: result } : { }


function timeout(tempo) {
    setTimeout(function () {;
        return timeout(tempo);
    }, 60000/tempo);

It just goes on and on. I tried to create a public worker in myApp.ts, so I could use this.worker.terminate();. Unfortunately, this isn’t possible.

I hope someone has an idea about how to stop the infinite worker loop…
(Start-Button to start the worker loop, Stop-Button to terminate the worker loop).


I initialized the worker in the constructor and now it even works with this.worker.
Problem solved :slight_smile:


I’d suggest that you instantiate just 1(2) worker(s) and delegating playing sound to them instead of terminating them every time the sound is over. Creating a new Worker can be very expensive.


But isn’t that what I’m doing right now? The loop is technically endless and 1 Worker is being used for this loop, until it gets shutdown by the Stop-Button.


I read through the lines, you are correct.