Reactive-Extensions/RxJS

View on GitHub
modules/rx-lite-async/rx.lite.async.js

Summary

Maintainability
F
1 wk
Test Coverage
// Copyright (c) Microsoft, All rights reserved. See License.txt in the project root for license information.
 
Similar blocks of code found in 2 locations. Consider refactoring.
;(function (factory) {
var objectTypes = {
'function': true,
'object': true
};
 
function checkGlobal(value) {
return (value && value.Object === Object) ? value : null;
}
 
var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : null;
var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : null;
var freeGlobal = checkGlobal(freeExports && freeModule && typeof global === 'object' && global);
var freeSelf = checkGlobal(objectTypes[typeof self] && self);
var freeWindow = checkGlobal(objectTypes[typeof window] && window);
var moduleExports = (freeModule && freeModule.exports === freeExports) ? freeExports : null;
var thisGlobal = checkGlobal(objectTypes[typeof this] && this);
var root = freeGlobal || ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')();
 
// Because of build optimizers
if (typeof define === 'function' && define.amd) {
define(['./rx.lite'], function (Rx, exports) {
return factory(root, exports, Rx);
});
} else if (typeof module === 'object' && module && module.exports === freeExports) {
module.exports = factory(root, module.exports, require('rx-lite'));
} else {
root.Rx = factory(root, {}, root.Rx);
}
}.call(this, function (root, exp, Rx, undefined) {
 
// Aliases
var Observable = Rx.Observable,
observableFromPromise = Observable.fromPromise,
observableThrow = Observable.throwError,
AnonymousObservable = Rx.AnonymousObservable,
ObservableBase = Rx.ObservableBase,
AsyncSubject = Rx.AsyncSubject,
disposableCreate = Rx.Disposable.create,
CompositeDisposable = Rx.CompositeDisposable,
immediateScheduler = Rx.Scheduler.immediate,
defaultScheduler = Rx.Scheduler['default'],
inherits = Rx.internals.inherits,
isScheduler = Rx.Scheduler.isScheduler,
isPromise = Rx.helpers.isPromise,
isFunction = Rx.helpers.isFunction,
isIterable = Rx.helpers.isIterable,
isArrayLike = Rx.helpers.isArrayLike;
 
Observable.wrap = function (fn) {
function createObservable() {
return Observable.spawn.call(this, fn.apply(this, arguments));
}
 
createObservable.__generatorFunction__ = fn;
return createObservable;
};
 
Function `spawn` has 42 lines of code (exceeds 25 allowed). Consider refactoring.
var spawn = Observable.spawn = function () {
var gen = arguments[0], self = this, args = [];
for (var i = 1, len = arguments.length; i < len; i++) { args.push(arguments[i]); }
 
return new AnonymousObservable(function (o) {
var g = new CompositeDisposable();
 
if (isFunction(gen)) { gen = gen.apply(self, args); }
if (!gen || !isFunction(gen.next)) {
o.onNext(gen);
return o.onCompleted();
}
 
function processGenerator(res) {
var ret = tryCatch(gen.next).call(gen, res);
if (ret === errorObj) { return o.onError(ret.e); }
next(ret);
}
 
processGenerator();
 
function onError(err) {
var ret = tryCatch(gen.next).call(gen, err);
if (ret === errorObj) { return o.onError(ret.e); }
next(ret);
}
 
function next(ret) {
if (ret.done) {
o.onNext(ret.value);
o.onCompleted();
return;
}
var obs = toObservable.call(self, ret.value);
var value = null;
var hasValue = false;
if (Observable.isObservable(obs)) {
g.add(obs.subscribe(function(val) {
hasValue = true;
value = val;
}, onError, function() {
hasValue && processGenerator(value);
}));
} else {
onError(new TypeError('type not supported'));
}
}
 
return g;
});
};
 
function toObservable(obj) {
if (!obj) { return obj; }
if (Observable.isObservable(obj)) { return obj; }
if (isPromise(obj)) { return Observable.fromPromise(obj); }
if (isGeneratorFunction(obj) || isGenerator(obj)) { return spawn.call(this, obj); }
Avoid too many `return` statements within this function.
if (isFunction(obj)) { return thunkToObservable.call(this, obj); }
Avoid too many `return` statements within this function.
if (isArrayLike(obj) || isIterable(obj)) { return arrayToObservable.call(this, obj); }
Avoid too many `return` statements within this function.
if (isObject(obj)) {return objectToObservable.call(this, obj);}
Avoid too many `return` statements within this function.
return obj;
}
 
function arrayToObservable (obj) {
return Observable.from(obj).concatMap(function(o) {
if(Observable.isObservable(o) || isObject(o)) {
return toObservable.call(null, o);
} else {
return Rx.Observable.just(o);
}
}).toArray();
}
 
function objectToObservable (obj) {
var results = new obj.constructor(), keys = Object.keys(obj), observables = [];
for (var i = 0, len = keys.length; i < len; i++) {
var key = keys[i];
var observable = toObservable.call(this, obj[key]);
 
if(observable && Observable.isObservable(observable)) {
defer(observable, key);
} else {
results[key] = obj[key];
}
}
 
return Observable.forkJoin.apply(Observable, observables).map(function() {
return results;
});
 
 
function defer (observable, key) {
results[key] = undefined;
observables.push(observable.map(function (next) {
results[key] = next;
}));
}
}
 
function thunkToObservable(fn) {
var self = this;
return new AnonymousObservable(function (o) {
fn.call(self, function () {
var err = arguments[0], res = arguments[1];
if (err) { return o.onError(err); }
if (arguments.length > 2) {
var args = [];
for (var i = 1, len = arguments.length; i < len; i++) { args.push(arguments[i]); }
res = args;
}
o.onNext(res);
o.onCompleted();
});
});
}
 
function isGenerator(obj) {
return isFunction (obj.next) && isFunction (obj['throw']);
}
 
function isGeneratorFunction(obj) {
var ctor = obj.constructor;
if (!ctor) { return false; }
if (ctor.name === 'GeneratorFunction' || ctor.displayName === 'GeneratorFunction') { return true; }
return isGenerator(ctor.prototype);
}
 
function isObject(val) {
return Object == val.constructor;
}
 
/**
* Invokes the specified function asynchronously on the specified scheduler, surfacing the result through an observable sequence.
*
* @example
* var res = Rx.Observable.start(function () { console.log('hello'); });
* var res = Rx.Observable.start(function () { console.log('hello'); }, Rx.Scheduler.timeout);
* var res = Rx.Observable.start(function () { this.log('hello'); }, Rx.Scheduler.timeout, console);
*
* @param {Function} func Function to run asynchronously.
* @param {Scheduler} [scheduler] Scheduler to run the function on. If not specified, defaults to Scheduler.timeout.
* @param [context] The context for the func parameter to be executed. If not specified, defaults to undefined.
* @returns {Observable} An observable sequence exposing the function's result value, or an exception.
*
* Remarks
* * The function is called immediately, not during the subscription of the resulting sequence.
* * Multiple subscriptions to the resulting sequence can observe the function's result.
*/
Observable.start = function (func, context, scheduler) {
return observableToAsync(func, context, scheduler)();
};
 
/**
* Invokes the asynchronous function, surfacing the result through an observable sequence.
* @param {Function} functionAsync Asynchronous function which returns a Promise to run.
* @returns {Observable} An observable sequence exposing the function's result value, or an exception.
*/
Observable.startAsync = function (functionAsync) {
var promise = tryCatch(functionAsync)();
if (promise === errorObj) { return observableThrow(promise.e); }
return observableFromPromise(promise);
};
 
return Rx;
}));