Skip to content

Commit

Permalink
Merge branch 'master' into gh-pages
Browse files Browse the repository at this point in the history
* master:
  cleanup repository after release
  1.1.0
  improve release scripts
  more on loops in .repeat
  note about infinite loops with .repeat
  add Kefir.repeat() method
  fix a bug in .merge and .zip
  add .emitEvent (fix #51)
  update deps
  check emitter to be instance of Emitter (in test spec)
  • Loading branch information
rpominov committed Feb 15, 2015
2 parents 82b3e13 + 09cb0ae commit b7fb44d
Show file tree
Hide file tree
Showing 22 changed files with 459 additions and 28 deletions.
8 changes: 4 additions & 4 deletions Gruntfile.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ module.exports = (grunt) ->
grunt.registerTask 'build-kefir', ['concat:kefir', 'uglify:kefir']
grunt.registerTask 'test', ['jasmine_node:main', 'jshint:main']
grunt.registerTask 'build-docs', ['jade:docs']
grunt.registerTask 'release-patch', ['bump', 'release']
grunt.registerTask 'release-minor', ['bump:minor', 'release']
grunt.registerTask 'release-major', ['bump:major', 'release']
grunt.registerTask 'release-pre', ['bump:prerelease', 'release']
grunt.registerTask 'release-patch', ['bump', 'release', 'post-release']
grunt.registerTask 'release-minor', ['bump:minor', 'release', 'post-release']
grunt.registerTask 'release-major', ['bump:major', 'release', 'post-release']
grunt.registerTask 'release-pre', ['bump:prerelease', 'release', 'post-release']
grunt.registerTask 'default', [
'clean', 'build-docs', 'build-kefir', 'build-browser-tests', 'test']

Expand Down
4 changes: 2 additions & 2 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kefir",
"version": "1.0.0",
"version": "1.1.0",
"homepage": "https://github.com/pozadi/kefir",
"authors": [
"Roman Pominov <rpominov@gmail.com>"
Expand Down Expand Up @@ -34,7 +34,7 @@
"!LICENSE.txt"
],
"devDependencies": {
"bacon": "0.7.43",
"bacon": "0.7.48",
"jquery": "1.11.1",
"jasmine-reporters": "git@github.com:larrymyers/jasmine-reporters.git#0.4.1",
"coffeescript": "git@github.com:jashkenas/coffeescript.git#1.9.0",
Expand Down
12 changes: 9 additions & 3 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 1.1.0

- The `Bus` and `Pool` classes are exposed as `Kefir.Bus` and `Kefir.Pool`
- A bug in `.merge` and `.zip` fixed which may cause them to not unsubscribe from their sources in very rare cases
- New method `.emitEvent` in Emitter, Emitter Object, and Bus
- New method `Kefir.repeat`

## 1.0.0

- jQuery plugin moved to a [separate repo](https://github.com/pozadi/kefir-jquery)
Expand Down Expand Up @@ -26,11 +33,10 @@
## 0.5.0

- Base errors support added (i.e. errors flow through all kind of transformations/combinations)
- Properties now may have a current error (as well as current value)
- New method `.onError`
- New method `.offError`
- Emitter now has `.error` method for emitting errors
- Emitter object also now has `.error` method
- Properties now may have a current error (as well as current value)
- New method `.error` in Emitter, Emitter Object, and Bus
- New method `Kefir.constantError`
- New method `.mapErrors`
- New method `.filterErrors`
Expand Down
95 changes: 91 additions & 4 deletions docs-src/descriptions/create.jade
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ h2#create-stream Create a stream

+descr-method('emitter', 'emitter', 'Kefir.emitter()').
Creates an emitter, that is ordinary stream, but also has additional methods:
#[tt .emit(value)], #[tt .error(error)], and #[tt .end()].
Once an emitter was created, one can easily emit all three kind of events to it,
#[tt .emit(value)], #[tt .error(error)], #[tt .end()], and #[tt .emitEvent()].
The first three are pretty self-descriptive, and the last one accepts event object with same format
as in #[a(href='#on-any') onAny] method and emits the event.
Once an emitter was created, one can easily emit all three kind of events from it,
using these methods.

pre(title='example').
Expand All @@ -26,12 +28,12 @@ pre(title='events in time').
div

p.
<img data-emoji="point_up"> #[b Emitter] is the easiest way
#[img(data-emoji="point_up")] #[b Emitter] is the easiest way
to create general purpose streams,
but it doesn't give you control over the #[a(href='#active-state') active state]
of the stream — it doesn't allows you to monitor if the stream has subscribers or not,
and sub/unsub to your original source or doing other resource management based on
whether stream has subscribers or not. If you want to have that control, you should use
that. If you want to have that control, you should use
#[a(href='#from-binder') fromBinder] or #[a(href='#from-sub-unsub') fromSubUnsub].


Expand Down Expand Up @@ -418,6 +420,91 @@ div




+descr-method('repeat', 'repeat', 'Kefir.repeat(generator)').
Calls #[b generator] function which supposed to return an observable.
Emits values and errors from spawned observable, when it ends
calls #[b generator] again to get new one and so on.

p.
The #[b generator] function is called with one argument — iteration number
starting from #[tt 0]. If a falsy value returned
from #[b generator] the stream ends.

pre(title='example')
:escapehtml
var result = Kefir.repeat(function(i) {
if (i < 3) {
return Kefir.sequentially(100, [i, i]);
} else {
return false;
}
});
result.log();

pre(title='console output')
:escapehtml
> [repeat] <value> 0
> [repeat] <value> 0
> [repeat] <value> 1
> [repeat] <value> 1
> [repeat] <value> 2
> [repeat] <value> 2
> [repeat] <end>

pre(title='events in time').
spawned 1: ---0---0X
spawned 2: ---1---1X
spawned 3: ---2---2X

result: ---0---0---1---1---2---2X
div

p.
#[img(data-emoji="point_up")] Note that with this method
it's possible to create an infinite loop. Consider this example:

pre(title='example')
:escapehtml
var result = Kefir.repeat(function() {
return Kefir.constant(1);
});

// When we subscribe to it (directly or via .log)
// we already in infinite loop.
result.log();

// But if we limit it with .take or something it'll work just fine.
// So the `result` stream defined like this
// still may make sense depend on how we use it.
result.take(10).log();

p.
It's even more dangerous if #[b generator] constantly returns ended observable
with no values (e.g. #[a(href='#never') never]).
In this case #[tt .take] won't help, because you'll never get any single
value from it, but #[b generator] will be called over and over.
The only escape path here is to define an escape condition it the
#[b generator]:

pre(title='example')
:escapehtml
var result = Kefir.repeat(function(i) {

// Defining that a new observable will be spawned at most 10 times
if (i >= 10) {
return false;
}

return Kefir.never();
});

p.
So just be careful when using #[b repeat],
it's a little dangerous but still a great method.



h2#create-property Create a property


Expand Down
8 changes: 6 additions & 2 deletions docs-src/descriptions/emitter-object.jade
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
h2#emitter-object Emitter object

p.
Emitter object is an object, that has three methods #[b emit], #[b error], and #[b end].
Emitter object is an object, that has four methods for emitting events.
It is used in several places in Kefir as a proxy to emit events to some observable.

p.
The methods names describe themself pretty clearly:

ul
li #[tt emiter.emit(value)] accepts one argument (any value)
li #[tt emiter.error(error)] accepts one argument (any value)
li #[tt emiter.end()] accepts no arguments
li #[tt emiter.emitEvent(event)] accepts one agrument (event object with same format as in #[a(href='#on-any') onAny] method). Note that the #[tt current] property of #[b event object] are ignored and automatically set to appropriate value for result event.

pre
:escapehtml
Expand All @@ -21,7 +25,7 @@ p.
They both have similar methods,
but #[b emitter object] isn't actually a stream,
it has no stream methods or functionality.
Emitter object has only three methods, that's it.
Emitter object has only four methods, that's it.

p.
All #[b emitter object] methods are bound to its context,
Expand Down
1 change: 1 addition & 0 deletions docs-src/includes/side-menu.jade
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ ul.toc-section
+method('#from-event', 'fromEvent')
+method('#from-sub-unsub', 'fromSubUnsub')
+method('#from-binder', 'fromBinder')
+method('#repeat', 'repeat')

a.toc-title(href='#create-property') Create a property
ul.toc-section
Expand Down
6 changes: 5 additions & 1 deletion grunt-tasks/bump.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ module.exports = function(grunt){
grunt.file.write('bower.json', JSON.stringify(bower, null, ' ') + '\n');
grunt.log.ok('bumped version in bower.json to ' + pkg.version);

run('NODE_PATH=./dist grunt'); // lol
run('grunt'); // lol
run('grunt bower'); // lol
run('git add .');
run('git add -f dist');
run('git add -f index.html');
run('git add -f bower-packages');
run('git add -f test/in-browser/spec/KefirSpecs.js');
run('git commit -m "'+ pkg.version +'"');
run('git push');

Expand Down
27 changes: 27 additions & 0 deletions grunt-tasks/post-release.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
var semver = require('semver');
var shell = require('shelljs');




module.exports = function(grunt){
grunt.registerTask('post-release', 'cleanup repository after release', function(type){

function run(cmd){
if (shell.exec(cmd, {silent:false}).code === 0){
grunt.log.ok(cmd + ' ...success');
} else{
grunt.fail.warn('Failed when executing: `' + cmd + '`\n')
}
}


run('git rm -r dist');
run('git rm -r bower-packages');
run('git rm index.html');
run('git rm test/in-browser/spec/KefirSpecs.js');
run('git commit -m "cleanup repository after release"');
run('git push');
});
};

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kefir",
"version": "1.0.0",
"version": "1.1.0",
"description": "Reactive Programming library for JavaScript inspired by Bacon.js and RxJS with focus on high performance and low memory usage",
"main": "dist/kefir.js",
"scripts": {
Expand Down Expand Up @@ -29,7 +29,7 @@
},
"license": "MIT",
"devDependencies": {
"baconjs": "0.7.43",
"baconjs": "0.7.48",
"benchmark": "1.0.0",
"coffee-script": "1.9.0",
"coffeeify": "1.0.0",
Expand All @@ -39,14 +39,15 @@
"grunt-cli": "0.1.13",
"grunt-contrib-clean": "0.6.0",
"grunt-contrib-concat": "0.5.0",
"grunt-contrib-jade": "0.14.0",
"grunt-contrib-jade": "0.14.1",
"grunt-contrib-jshint": "0.11.0",
"grunt-contrib-uglify": "0.7.0",
"grunt-contrib-watch": "0.6.1",
"grunt-jasmine-node": "0.2.1",
"grunt-jasmine-node": "git+https://git@github.com/pozadi/grunt-jasmine-node.git",
"grunt-release": "0.7.0",
"jasmine-node": "1.14.5",
"load-grunt-tasks": "3.1.0",
"rx": "2.3.24",
"rx": "2.3.25",
"semver": "2.3.0",
"shelljs": "0.3.0",
"sinon": "1.12.2",
Expand Down
3 changes: 2 additions & 1 deletion src/interval.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ withInterval('withInterval', {
this._emitter = {
emit: function(x) { $._send(VALUE, x) },
error: function(x) { $._send(ERROR, x) },
end: function() { $._send(END) }
end: function() { $._send(END) },
emitEvent: function(e) { $._send(e.type, e.value) }
}
},
_free: function() {
Expand Down
13 changes: 11 additions & 2 deletions src/multiple-sources.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ inherit(_AbstractPool, Stream, {
var sources = this._curSources
, i;
this._activating = true;
for (i = 0; i < sources.length; i++) { this._subscribe(sources[i]) }
for (i = 0; i < sources.length; i++) {
if (this._active) {
this._subscribe(sources[i]);
}
}
this._activating = false;
},
_onDeactivation: function() {
Expand Down Expand Up @@ -234,6 +238,9 @@ inherit(Bus, _AbstractPool, {
end: function() {
this._send(END);
return this;
},
emitEvent: function(event) {
this._send(event.type, event.value);
}

});
Expand Down Expand Up @@ -370,7 +377,9 @@ inherit(Zip, Stream, {
this._drainArrays();
this._aliveCount = length;
for (i = 0; i < length; i++) {
this._sources[i].onAny(this._bindHandleAny(i), [this, i]);
if (this._active) {
this._sources[i].onAny(this._bindHandleAny(i), [this, i]);
}
}
},

Expand Down
3 changes: 2 additions & 1 deletion src/one-source.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ withOneSource('withHandler', {
this._emitter = {
emit: function(x) { $._send(VALUE, x, $._forcedCurrent) },
error: function(x) { $._send(ERROR, x, $._forcedCurrent) },
end: function() { $._send(END, null, $._forcedCurrent) }
end: function() { $._send(END, null, $._forcedCurrent) },
emitEvent: function(e) { $._send(e.type, e.value, $._forcedCurrent) }
}
},
_free: function() {
Expand Down

0 comments on commit b7fb44d

Please sign in to comment.