github Reactive-Extensions/RxJS v2.3.12
RxJS Version 2.3

latest releases: v4.1.0, v4.0.8, v4.0.7...
9 years ago

This is the first stable release of RxJS version 2.3. This has been a long time in the making and thank you to the community for help making this happen. There are a lot of exciting things in store for RxJS in this release including a custom build system, a commitment to standards, as well as handy things such as smaller Rx-Lite builds.

There are many changes in this release including:

  • A Commitment to Standards
  • Custom Builds
  • A lighter Lite
  • New Operators
  • Operator Changes

A Commitment to Standards

We on the RxJS team are committed to standards put out by TC39 and the JavaScript community. We will try to add features to take advantage of browser and runtime features as they become available, allowing RxJS to really shine!

Promises Promises

For example, you will find many operators that gladly accept Promise objects as parameters which are then converted to RxJS Observable objects. RxJS will use the native Promise object if present in the browser, but can also be configured to use your own library as long as it follows the ES6 standard for construction. Such libraries include RSVP, Q, when.js, and more.

To specify which promise library to use, you can specify it in the Rx.config.Promise property. Note that this is only used if you use Rx.Observable.prototype.toPromise operator.

Some of the operators that support promises natively include:

  • Rx.Observable.amb | Rx.Observable.prototype.amb
  • Rx.Observable.case
  • Rx.Observable.catch | Rx.Observable.prototype.catch
  • Rx.Observable.combineLatest | Rx.Observable.prototype.combineLatest
  • Rx.Observable.concat | Rx.Observable.prototype.concat
  • Rx.Observable.prototype.concatMap
  • Rx.Observable.prototype.concatMapObserver
  • Rx.Observable.defer
  • Rx.Observable.prototype.flatMap
  • Rx.Observable.prototype.flatMapLatest
  • Rx.Observable.forkJoin | Rx.Observable.prototype.forkJoin
  • Rx.Observable.if
  • Rx.Observable.merge
  • Rx.Observable.prototype.mergeAll
  • Rx.Observable.onErrorResumeNext | Rx.Observable.prototype.onErrorResumeNext
  • Rx.Observable.prototype.selectMany
  • Rx.Observable.prototype.selectSwitch
  • Rx.Observable.prototype.sequenceEqual
  • Rx.Observable.prototype.skipUntil
  • Rx.Observable.startAsync
  • Rx.Observable.prototype.switch
  • Rx.Observable.prototype.takeUntil
  • Rx.Observable.prototype.throttleWithSelector
  • Rx.Observable.prototype.timeoutWithSelector
  • Rx.Observable.while
  • Rx.Observable.prototype.window
  • Rx.Observable.zip | Rx.Observable.prototype.zip

Array Extras Redux

In addition, we have implemented a number of operators on Observable to mimic what is coming in ES Next for Arrays including:

  • Rx.Observable.from
  • Rx.Observable.of
  • Rx.Observable.prototype.contains
  • Rx.Observable.prototype.indexOf

Maps and Sets

We also want to support the new data structures coming in a browser near you. Consider that we already have Rx.Observable.prototype.toArray, we will now support converting to a Set or Map if they are available in your environment via:

  • Rx.Observable.prototype.toMap
  • Rx.Observable.prototype.toSet

Generators Support

But, we're not done yet, because now we also have support for generators with Rx.Observable.spawn which allows you to use RxJS in an async/await style in addition to Promises and callbacks.

var Rx = require('rx');
var request = require('request').request;
var get = Rx.Observable.fromNodeCallback(request);

Rx.spawn(function* () {
  var data;
  try {
    var data = yield get('http://bing.com').retry(3);
  } catch (e) {
    console.log('Error %s', e);
  } 

  console.log(data);
});

You can also use generators with Rx.Observable.from as well, for example this Fibonacci server.

function* fibonacci(){
  var fn1 = 1;
  var fn2 = 1;
  while (1){
    var current = fn2;
    fn2 = fn1;
    fn1 = fn1 + current;
    yield current;
  }
}

Rx.Observable.from(fibonacci())
  .take(10)
  .subscribe(function (x) {
    console.log('Value: %s', x);
  });

//=> Value: 1
//=> Value: 1
//=> Value: 2
//=> Value: 3
//=> Value: 5
//=> Value: 8
//=> Value: 13
//=> Value: 21
//=> Value: 34
//=> Value: 55

And we're just getting started, with looking at Object.observe and other places where RxJS can make your development experience better.

Custom Builds

Custom builds are an exciting new piece of RxJS to allow you to include the operators you wish. We have many files that contain many operators, however, it may come down to only wanting a handful of them to keep the size of your file to a minimum. With the rx-cli project, you have that ability to specify methods, either directly in the command prompt or in a file, and also specify whether you want to have a compatibility build to handle older browsers.

For example, you can specify you with only just a few operators to be included.

$ {sudo} npm install -g rx-cli
$ rx --compat --methods map,flatmap,flatmaplatest,takeuntil,fromevent,filter 

This is still an early version and feedback is welcome!

A Liter Lite`

One main goal of RxJS to make the most used operators easily available in a smaller sized package, as in rx.lite.js. In this release, we have made rx.lite.js even smaller, down to 9kb gzipped.

To that end, the following time-bsed operators have been removed from rx.lite.js entirely:

  • Rx.Observable.prototype.delaySubscription
  • Rx.Observable.prototype.delayWithSelector
  • Rx.Observable.prototype.skipLastWithTime
  • Rx.Observable.prototype.skipUntilWithTime
  • Rx.Observable.prototype.takeLastWithTime
  • Rx.Observable.prototype.takeLastBufferWithTime
  • Rx.Observable.prototype.takeUntilWithTime
  • Rx.Observable.prototype.throttleWithSelector
  • Rx.Observable.prototype.timeoutWithSelector

If you still need those operators, it's very easy to just pull in rx.time.js which has all of those operators. In addition, anything that was in rx.js that is not in rx.lite.js is kept in rx.lite.extras.js to minimize size once again.

New Operators

RxJS added a few new operators in this release to keep parity with RxJava and Rx .NET.

There are the aforementioned operators from the Array#extras and ES Next features including:

  • Rx.Observable.from
  • Rx.Observable.of
  • Rx.Observable.prototype.contains
  • Rx.Observable.prototype.indexOf

There are other new operators that were introduced to bring compatibility with the Reactive Extensions for .NET:

Operator Changes

There were also a number of changes that were introduced to operators that altered their behavior from version 2.2.

Node.js Support

Node.js support grew during this release to further support the new Streams. To that end, we made the following changes:

  • Allowed objectMode to be set so that items are pushed in their native format instead of in a Buffer or String when using Rx.Node.writeToStream
  • Fixed Rx.Node.fromStream so that is uses the 'end' event by default to signify the end of a stream, but allows to be overridden.
  • Created the following toStream shortcuts to support all streams
    • Rx.Node.fromReadableStream
    • Rx.Node.fromWritableStream
    • Rx.Node.fromTransformStream

Rx.Observable.fromEvent changes

There were a number of changes in how Rx.Observable.fromEvent worked. We wanted to ensure that fromEvent was as flexible as possible to utilize the framework you were already using, but also, to use just plain old events just in case.

First off, we added support for Backbone and Backbone Marionette which then brings us up to supporting the following libraries natively:

  • Angular.js - angular.element.on and angular.element.off
  • Backbone and Marionette - binds to element.addListener and element.removeListener
  • Ember - binds to Ember.addListener and Ember.removeListener
  • jQuery - binds to jQuery.fn.on and jQuery.fn.off
  • Zepto.js - binds to Zepto.fn.on and Zepto.fn.off

Although we support using these events if they are present, we also offer a way to opt out and only use DOM or Node.js specific events only. By setting the Rx.config.useNativeEvents flag to true, this will only use native DOM events or in Node.js if you're using Node.

Rx.config.useNativeEvents = true;

var mousemove = Rx.Observable.fromEvent(document, 'mousemove');

// Note since jQuery unwraps, this is stil supported
var mousemove = Rx.Observable.fromEvent($document, 'mousemove');

Renaming of Rx.Observable.prototype.then

Libraries that use Promises typically do a check to see whether it is a promise by doing the following:

function isPromise(p) { 
  return p && p.then && typeof p.then === 'function';
}

The problem with that is that RxJS also had a then method which caused the function to return true, although the RxJS then has nothing to do with Promises, and instead has to deal with join patterns/join calculus. In order to prevent collision with Promise libraries, we have renamed Rx.Observable.prototype.then to Rx.Observable.prototype.thenDo so there should be no more false positives when it comes to checking whether an object is a Promise.

Moving Operators

Another change was moving some operators to a different file to keep the core size of rx.js smaller. This includes moving Rx.Observable.prototype.groupBy and Rx.Observable.prototype.groupByUntil to rx.coincidence.js to go along with other coincidence operators such as groupJoin, join, buffer and window.

Changing Method signatures

There were a few changes to some method signatures as well due to feedback from the community and looking at its usage. This shouldn't affect many people as the changes are very slight. In fact, you may not notice them at all.

Callback Changes

The first such change was to remove the schedulers required from Rx.Observable.fromCallback and Rx.Observable.fromNodeCallback. The reason is that the concurrency is already handled by the callback, there is no need to introduce another layer of concurrency.

Below is the old version which had schedulers as a parameter.

Rx.Observable.fromCallback = function (func, scheduler, context, selector) {
Rx.Observable.fromNodeCallback = function (func, scheduler, context, selector) {

And here is the updated version which removes the schedulers.

Rx.Observable.fromCallback = function (func, context, selector) {
Rx.Observable.fromNodeCallback = function (func, context, selector) {

Now you can easily use the callback functions such as:

var $elem = $('#elem');
var fadeIn = Rx.Observable.fromCallback($elem.fadeIn, $elem)(1000);

Start and ToAsync Changes

There was another change of ordering of parameters for a couple of methods Rx.Observable.start and Rx.Observable.toAsync where it made the API a bit nicer. Before, the scheduler, which was usually set by default, was the second parameter, and was moved to the third parameter as it was purely optional. The context was instead moved to the second parameter as it was more likely to be used.

Below is the old version which had the context third and scheduler second.

Rx.Observable.start = function (func, scheduler, context) {
Rx.Observable.toAsync = function (func, scheduler, context) {

Now the last two parameters have been reversed.

Rx.Observable.start = function (func, context, scheduler) {
Rx.Observable.toAsync = function (func, context, scheduler) {

This allows for much smoother behavior when a context is needed.

function logMessage(msg) {
  this.log('Message: %s', msg);
}

var asyncLog = Rx.Observable.toAsync(logMessage, console);

asyncLog('foobar').subscribe();
// => Message: foobar

Conclusion

We hope you enjoy these new and changed features of RxJS. We'd love your feedback by creating issues for us, pull requests and so forth. Documentation, tutorials and other things welcome!

Don't miss a new RxJS release

NewReleases is sending notifications on new releases.