Leahcim
Leahcim

Reputation: 41949

what is the Ember implementation of setInterval and clearInterval

Ember has the following implementation of setTimeout, which it is recommended developers use because the code gets added to the run loop, which has advantages for tests.

           Ember.run.later((function() {
               console.log("will run once after 1000");
           }), 1000); 

Is there a similar Ember replacement for setInterval and, by implication, clearInterval (which is used to cancel a setInterval)? I need to run someFunc every 1000 ms

this.intervalId = setInterval(this.someFunc.bind(this), 1000);

Upvotes: 8

Views: 5862

Answers (4)

needprayfornotaxes
needprayfornotaxes

Reputation: 131

I have been playing around with implement "setInterval" in Ember Octane way and I think this is THE MOST SIMPLE and CLEAN solution:

index.hbs:

{{this.counter}}
<button {{on "click" this.start}}>Start</button>
<button {{on "click" this.stop}}>Stop</button>
<button {{on "click" this.reset}}>Reset</button>

controllers/index.js

import Controller from '@ember/controller';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { cancel, later, next } from '@ember/runloop';

export default class IndexController extends Controller {
  @tracked counter = 0;
  runner = null;

  @action start() {
    next(this, function () {
      this.runner = this.tick();
    });
  }

  @action stop() {
    cancel(this.runner);
  }

  @action reset() {
    this.counter = 0;
  }

  tick() {
    return later(this, function () {
      this.counter++;
      this.runner = this.tick();
    }, 1000);
  }    
}

result in browser

Upvotes: 3

siwalikm
siwalikm

Reputation: 1865

Tested in ember -v 1.18

This is what I've been doing inside my component. This works perfectly fine and should be the ideal way of approaching. If you're handling async promise objects inside the interval, make sure to kill it in willDestroyElement() hook or somewhere.

init() {
  this._super(...arguments);
  this.startAutoSaveTimer();
},

startAutoSaveTimer() {
  let autosaveFunc = function() {
    console.info('Arr .. I'm a pirate!');
  };
  set(this, 'timerInstance', setInterval(autosaveFunc, 1000));
},

Upvotes: 0

Jacob van Lingen
Jacob van Lingen

Reputation: 9537

Another option is to use the ember-poll add-on. Internally, it does somewhat the same as @andrusieczko Poller object (both take the Ember Run Loop into account). From an Ember developer view, you get access to a poll service.

Just install the add-on: npm install ember-poll --save-dev.


Example:

import Ember from 'ember';

export default Ember.Route.extend({
  poll: Ember.service.inject(),

  setupController() {
    this._super(...arguments);

    this.get('poll').addPoll({
      interval: 1000,
      label: 'my-poll',
      callback: () => {
        //do something every second
      }
    }); 
  },

  actions: {
    willTransition() {
      this.get('poll').clearPollByLabel('my-poll');
    }
  }
}

Upvotes: 1

andrusieczko
andrusieczko

Reputation: 2824

I'm not aware of any equivalent, but I use such a code to have the functionality:

var Poller = Ember.Object.extend({

  _interval: 1000,
  _currentlyExecutedFunction: null,

  start: function(context, pollingFunction) {
    this.set('_currentlyExecutedFunction', this._schedule(context, pollingFunction, [].slice.call(arguments, 2)));
  },

  stop: function() {
    Ember.run.cancel(this.get('_currentlyExecutedFunction'));
  },

  _schedule: function(context, func, args) {
    return Ember.run.later(this, function() {
      this.set('_currentlyExecutedFunction', this._schedule(context, func, args));
      func.apply(context, args);
    }, this.get('_interval'));
  },

  setInterval: function(interval) {
    this.set('_interval', interval);
  }

});

export
default Poller;

Then, you instantiate the poller: var poller = Poller.create() and then you can play with poller.start() and poller.stop() + set set the interval via poller.setInterval(interval).

In my code, I did more or less that way (polling the reports every 10 seconds):

_updateRunningReport: function(report) {
  var poller = new Poller();
  poller.setInterval(this.POLLING_INTERVAL);
  poller.start(this, function() {
    if (report.isRunning()) {
      this._reloadReport(report);
    } else {
      poller.stop();
    }
  });
  eventBus.onLogout(function() {
    poller.stop();
  });
},

Hope this helps...

Upvotes: 9

Related Questions