Skip to content

Instantly share code, notes, and snippets.

@cwharris
Forked from mattpodwysocki/CombineLatest.js
Last active December 11, 2015 20:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cwharris/4658319 to your computer and use it in GitHub Desktop.
Save cwharris/4658319 to your computer and use it in GitHub Desktop.
// combineLatest(obs1, obs2, selector)
// combineLatest([obs1, obs2], selector)
observableProto.combineLatest = function () {
var args = slice.call(arguments);
// (args[0] instanceof Array ? args[0] : args).unshift(this);
if (args[0] instanceof Array) {
args[0].unshift(this);
} else {
args.unshift(this);
}
combineLatest.apply(this, args);
};
// combineLatest(obs1, obs2, selector)
// combineLatest([obs1, obs2], selector)
var combineLatest = Observable.combineLatest = function () {
var args = slice.call(arguments), resultSelector = args.pop();
if (args[0] instanceof Array) {
args = args[0];
}
return new AnonymousObservable(function (observer) {
var falseFactory = function () { return false; },
n = args.length,
hasValue = arrayInitialize(n, falseFactory),
hasValueAll = false,
isDone = arrayInitialize(n, falseFactory),
values = new Array(n);
function next(i) {
var res;
hasValue[i] = true;
if (hasValueAll || (hasValueAll = hasValue.every(function (x) { return x; }))) {
try {
res = resultSelector.apply(null, values);
} catch (ex) {
observer.onError(ex);
return;
}
observer.onNext(res);
} else if (isDone.filter(function (x, j) { return j !== i; }).every(function (x) { return x; })) {
observer.onCompleted();
}
}
function done (i) {
isDone[i] = true;
if (isDone.every(function (x) { return x; })) {
observer.onCompleted();
}
}
var subscriptions = new Array(n);
for (var idx = 0; idx < n; idx++) {
(function (i) {
subscriptions[i] = new SingleAssignmentDisposable();
subscriptions[i].setDisposable(args[i].subscribe(function (x) {
values[i] = x;
next(i);
}, observer.onError.bind(observer), function () {
done(i);
}));
})(idx);
}
return new CompositeDisposable(subscriptions);
});
};
@cwharris
Copy link
Author

Having the non-prototypal is great! :)

I added some code to allow for invokation using an Array of observables. Alternatively, similar invokation could be done using the following, so it's not a huge deal:

Rx.Observable.combineLatest.apply(_, sources.push(selector));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment