Skip to content

Commit

Permalink
revising API, fixing tests, getting ready for new release
Browse files Browse the repository at this point in the history
  • Loading branch information
arjunmehta committed Jan 2, 2015
1 parent 55224a1 commit 1d78dca
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 76 deletions.
100 changes: 67 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,24 @@ This is much more efficient and much more reliable than using multiple `setInter

```javascript
// Alternative to setInterval
heart.onBeat(5, function(){
console.log("...Every 5 Beats");
heart.createEvent(5, function(heartbeat, last){
console.log("...Every 5 Beats forever");
});
heart.onBeat(1, function(){
console.log("...Every Single Beats");

heart.createEvent(1, function(heartbeat, last){
console.log("...Every Single Beat forever");
});

heart.createEvent(1, {repeat: 3}, function(heartbeat, last){
console.log("...Every Single Beat for 3 beats only");
if(last === true){
console.log("...the last time.")
}
});

// Alternative to setTimeout
heart.onceOnBeat(2, function(){
console.log("...After 2 Beats");
heart.createEvent(2, {repeat: 1}, function(heartbeat, last){
console.log("...Once after 2 Beats");
});
```

Expand Down Expand Up @@ -114,7 +122,7 @@ npm install
npm run benchmark
```

You'll see that the same task is performed
Have a look at the `benchmark.js` file in the tests directory to see how the benchmark is done.


## API
Expand All @@ -125,22 +133,25 @@ The API is fairly straightforward, though it's good to be aware of nuances in it
#### heartbeats.createHeart(heartrate, name);
Creates and returns a new `Heart` object.

The heart is registered in the module's list of hearts (see **heartbeats.heart()**). This is useful if you want to access heartbeats from different modules.
If you provide a name, the heart is registered in the module's list of hearts (see **heartbeats.heart()**). This is useful if you want to access heartbeats from different modules.

```javascript
// a new heart that beats every 2 seconds named "heartA"
var heart = heartbeats.createHeart(2000, "heartA");
```

If you don't provide a name, the heart will be given a unique id as its name.
If you don't provide a name, the heart will be returned but will not be added to the `heartbeats.hearts` object.

```javascript
var heart = heartbeats.createHeart(2000);
console.log(heart.name); // heart_kajg8i27tjhv
```

#### heartbeats.hearts
An object with all hearts that have been instantiated with a name.

#### heartbeats.heart(name)
Returns a `Heart` object from the managed list of hearts.
Returns a `Heart` object with a name from the managed list of hearts.

```javascript
// gets a heart named "heartA"
Expand All @@ -155,19 +166,20 @@ Removes the `Heart` from the internal managed list and clears the heartbeat inte
heartbeats.killHeart("heartA");
```

#### heart.setHeartrate(heartrate)
Updates the heartrate period of the `Heart` and returns the `Heart` object for chaining.
```javascript
heartbeats.heart("heartA").setHeartrate(3000);
```

#### heart.kill()
Clears the heartbeat interval and removes the Heart from the internal managed list if it exists there.

```javascript
heartbeats.heart("heartA").kill();
```


#### heart.setHeartrate(heartrate)
Updates the heartrate period of the `Heart` and returns the `Heart` object for chaining.
```javascript
heartbeats.heart("heartA").setHeartrate(3000);
```

#### heart.age
Gets the current number of beats that the heart has incremented in its lifetime.

Expand All @@ -181,30 +193,43 @@ heartbeats.heart("heartA").age;
#### heart.createPulse(name);
Returns a new Pulse object associated with the heart.

If you provide a name, the Pulse is added to the Heart's internal managed list of Pulses (ie. `heart.pulses`). This is useful if

```javascript
// creates a new pulse from the "heartA" heart(beat)
var pulse = heartbeats.heart("heartA").createPulse("A");
```

If you don't provide a name, the heart will be given a unique id as its name.
If you don't provide a name, the pulse will be returned without being added to the Heart's managed list of Pulses.

```javascript
var heart = heartbeats.createHeart(2000);
console.log(heart.name); // heart_kajg8i27tjhv
var pulseA = heartbeats.heart("heartA").createPulse();
```

#### heart.pulses
An object with all pulses belonging to the heart, that have been instantiated with a name.

#### heart.pulse(name);
Returns a new Pulse object from the heart's managed list of pulses.
Returns the Pulse object from the heart's managed list of pulses.
```javascript
var pulse = heartbeats.heart("heartA").pulse("A");
var pulseA = heartbeats.heart("heartA").pulse("A");
```

#### heart.killPulse(name);
Kills the pulse and removes it from the heart's managed list of pulses.
Kills the Pulse and removes it from the heart's managed list of Pulses.
```javascript
var pulse = heartbeats.heart("heartA").pulse("A");
```

#### pulse.kill()
Kills the pulse and removes it from its heart's managed list (if it exists there).

```javascript
// clears the pulse from memory
pulse.kill();
```


#### pulse.beat()
This synchronizes the pulse with its Heart. **This is the secret sauce**. Instead of using `Date().now()` or `Date().getTime()` to register an event time we match the time of the pulse with the heart.

Expand All @@ -215,15 +240,6 @@ Returns the `Pulse` object to chain if needed.
pulse.beat();
```

#### pulse.kill()
Kills the pulse and removes it from its heart's managed list.

```javascript
// clears the pulse from memory
pulse.kill();
```


#### pulse.missedBeats
The number of heartbeats that have passed since the pulse was last synchronized with `pulse.beat()`.

Expand All @@ -249,16 +265,34 @@ This method is slightly different from the other creation methods (ie. `createHe

This method will add a reoccuring event to the heart. Every `nth` beat specified by `beatInterval` will execute the supplied function. This method counts from the time you add the event. It's kind of like `setInterval`.



##### Options
`name`: Give the Event a custom name, so you can reference it, kill it, or modify it using `heart.event(name)`
`repeat`: Repeat the event a specified number of times (use `0` for infinite). By default, this is set to `0` or infinite. If set to a finite number, the event will be killed and cleared from memory once executed the last time.
`repeat`: default is `0` (infinite). Repeat the event a specified number of times (use `0` for infinite). If set to a finite number, the event will be killed and cleared from memory once executed the last time.

##### Callback Function
The callback function is called with `heartbeat` and `last` as arguments.

The following example creates a new event called `checkA`, on an existing heart named `heartA` that executes every 5th beat, repeats forever. The `last` argument passed to the callback will always be `false`.

```javascript
var event = heartbeats.heart("heartA").createEvent(5, {name: "checkA", repeat: 0}, function(){
var event = heartbeats.heart("heartA").createEvent(5, {name: "checkA", repeat: 0}, function(heartbeat, last){
console.log("does this every 5 beats");
});
```

The following example creates an anonymous event on the heart named `heartA` that excutes every 4th beats but stops once it has been executed 3 times.

```javascript
heartbeats.heart("heartA").createEvent(4, {repeat: 3}, function(heartbeat, last){
console.log("does this every 4 beats");
if(last === true){
console.log("this is the last execution of this method")
}
});
```

#### heart.event(name)
Returns the `Event` with the specified name from the heart.
```javascript
Expand Down
43 changes: 22 additions & 21 deletions lib/beatevent.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
var idCount = 0;

function BeatEvent(heart, interval, name, repeat, fn){
this.id = name;
this.heart = heart;
function BeatEvent(heart, interval, name, repeat, fn) {
this.id = name || "event_" + (Math.random()).toString(36) + idCount++;
this.heart = heart;

this.repeat = repeat;
this.executionCount = 0;
this.repeat = repeat || 0;
this.executionCount = 0;

this.done = false;
this.count = 0;
this.interval = Math.round(interval, 10);
this.fn = fn;
this.done = false;
this.count = 0;
this.schedule = Math.round(interval, 10);
this.fn = fn;
}

BeatEvent.prototype.execute = function(){

this.count++;
BeatEvent.prototype.execute = function() {

if(this.count === this.interval){
this.executionCount++;
this.fn(this.heart.heartbeat);
this.count = 0;
this.count++;

if(this.repeat !== 0 && this.executionCount >= this.repeat){
this.done = true;
if (this.count === this.schedule) {
this.executionCount++;
if (this.repeat !== 0 && this.executionCount >= this.repeat) {
this.done = true;
this.fn(this.heart.heartbeat, true);
} else {
this.fn(this.heart.heartbeat, false);
}
this.count = 0;
}
}
};

BeatEvent.prototype.kill = function() {
this.heart.killEvent(this.id);
this.heart.killEvent(this.id, this);
};

exports = module.exports = BeatEvent;
exports = module.exports = BeatEvent;
41 changes: 26 additions & 15 deletions lib/heart.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
var Pulse = require("./pulse.js");
var BeatEvent = require("./beatevent.js");

var idCount = 0;
var hearts = {};
var idCount = 0,
hearts;

function initialize(global_hearts) {
hearts = global_hearts;
return Heart;
}


// Heart

function Heart(heartrate, name) {

this.heartbeat = 0;
Expand Down Expand Up @@ -61,9 +64,11 @@ Heart.prototype.kill = Heart.prototype.destroy = function() {
// Pulses

Heart.prototype.newPulse = Heart.prototype.createPulse = function(name) {
this.killPulse(name);
var pulse = new Pulse(this, name);
this.pulses[pulse.id] = pulse;
if (name) {
this.killPulse(name);
this.pulses[pulse.id] = pulse;
}
return pulse;
};

Expand All @@ -87,14 +92,17 @@ Heart.prototype.createEvent = function(modulo, options, fn) {
options = {};
}

var name = options.name || "event_" + (Math.random()).toString(36) + idCount++;
var repeat = options.repeat || 0;
var name = options.name;
var repeat = options.repeat;
var event = new BeatEvent(this, modulo, name, repeat, fn);

prepEvents(this);
this.killEvent(name);
prepHeartForEvents(this);

if (name) {
this.killEvent(name);
this.eventList[name] = event;
}

var event = new BeatEvent(this, modulo, name, repeat, fn);
this.eventList[name] = event;
this.events.push(event);
event.index = this.events.length - 1;

Expand All @@ -105,11 +113,14 @@ Heart.prototype.event = function(name) {
return this.eventList[name];
};

Heart.prototype.killEvent = function(name) {
Heart.prototype.killEvent = function(name, beatevent) {
if (this.eventList[name] !== undefined) {
this.events[this.eventList[name].index] = undefined;
this.eventList[name] = undefined;
}
else{
this.events[beatevent.index] = undefined;
}
};

Heart.prototype.killAllEvents = function() {
Expand All @@ -120,7 +131,7 @@ Heart.prototype.killAllEvents = function() {
this.interval = setInterval(createInterval(this), this.heartrate);
};

function prepEvents(heart) {
function prepHeartForEvents(heart) {
if (heart.eventsExist === false) {
heart.eventsExist = true;
clearInterval(heart.interval);
Expand All @@ -129,8 +140,7 @@ function prepEvents(heart) {
}



// Heat Beat Loop
// Heart Beat Loop

function createInterval(heart) {

Expand All @@ -144,11 +154,12 @@ function createInterval(heart) {
return function() {

heart.heartbeat++;

for (var i = 0; i < events.length; i++) {
if (events[i] !== undefined) {
events[i].execute();
if (events[i].done === true) {
console.log("DONE DONE DONE EVENT");

This comment has been minimized.

Copy link
@Mindwalker2076

Mindwalker2076 Jul 6, 2015

Why is the console.log line here? If we get to this point, and the modules writes to the console, have we done something incorrectly, or should this line have been removed prior to the commit?

This comment has been minimized.

Copy link
@arjunmehta

arjunmehta Jul 6, 2015

Author Owner

Oops! Yes, that is not supposed to be there!
Will remove this in an update tonight :D
Thanks for pointing it out!

This comment has been minimized.

Copy link
@arjunmehta

arjunmehta Jul 7, 2015

Author Owner

Fixed in 3.1.1

events[i].kill();
}
}
Expand Down
11 changes: 6 additions & 5 deletions main.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
var hearts = {};
var Heart = require("./lib/heart.js").initialize(hearts);

function createHeart(heartrate, name) {
killHeart(name);
function createHeart(heartrate, name) {
var heart = new Heart(heartrate, name);
hearts[heart.id] = heart;
if (name) {
killHeart(name);
hearts[heart.id] = heart;
}
return heart;
}

function killHeart(name) {
if (hearts[name]) {
clearInterval(hearts[name].interval);
hearts[name] = undefined;
hearts[name].kill();
}
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "heartbeats",
"version": "2.0.0",
"version": "3.0.0",
"description": "A simple node.js module to very efficiently manage time-based events and objects.",
"main": "main.js",
"scripts": {
Expand Down
Loading

0 comments on commit 1d78dca

Please sign in to comment.