Skip to content

Commit aa30af2

Browse files
committed
fix(Observable.from): standardise arguments (remove map/context)
BREAKING CHANGE - Observable.from no longer supports the optional map function and associated context argument. This change has been reflected in the related constructors and their properties have been standardised.
1 parent bdf9094 commit aa30af2

File tree

8 files changed

+29
-256
lines changed

8 files changed

+29
-256
lines changed

spec/observables/IteratorObservable-spec.ts

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,6 @@ describe('IteratorObservable', () => {
3232
}).to.throw(Error, 'object is not iterable');
3333
});
3434

35-
it('should not accept non-function project', () => {
36-
expect(() => {
37-
IteratorObservable.create([], 42);
38-
}).to.throw(Error, 'when provided, `project` must be a function.');
39-
});
40-
4135
it('should emit members of an array iterator', (done: MochaDone) => {
4236
const expected = [10, 20, 30, 40];
4337
IteratorObservable.create([10, 20, 30, 40])
@@ -55,8 +49,6 @@ describe('IteratorObservable', () => {
5549
it('should emit members of an array iterator on a particular scheduler', () => {
5650
const source = IteratorObservable.create(
5751
[10, 20, 30, 40],
58-
(x: number) => x,
59-
null,
6052
rxTestScheduler
6153
);
6254

@@ -65,32 +57,12 @@ describe('IteratorObservable', () => {
6557
expectObservable(source).toBe('(abcd|)', values);
6658
});
6759

68-
it('should emit members of an array iterator on a particular scheduler, project throws', () => {
69-
const source = IteratorObservable.create(
70-
[10, 20, 30, 40],
71-
(x: number) => {
72-
if (x === 30) {
73-
throw 'error';
74-
}
75-
return x * x;
76-
},
77-
null,
78-
rxTestScheduler
79-
);
80-
81-
const values = { a: 100, b: 400 };
82-
83-
expectObservable(source).toBe('(ab#)', values);
84-
});
85-
8660
it('should emit members of an array iterator on a particular scheduler, ' +
8761
'but is unsubscribed early', (done: MochaDone) => {
8862
const expected = [10, 20, 30, 40];
8963

9064
const source = IteratorObservable.create(
9165
[10, 20, 30, 40],
92-
(x: number) => x,
93-
null,
9466
Rx.Scheduler.queue
9567
);
9668

@@ -110,43 +82,6 @@ describe('IteratorObservable', () => {
11082
source.subscribe(subscriber);
11183
});
11284

113-
it('should emit members of an array iterator, and project them', (done: MochaDone) => {
114-
const expected = [100, 400, 900, 1600];
115-
IteratorObservable.create([10, 20, 30, 40], (x: number) => x * x)
116-
.subscribe(
117-
(x: number) => { expect(x).to.equal(expected.shift()); },
118-
(x) => {
119-
done(new Error('should not be called'));
120-
}, () => {
121-
expect(expected.length).to.equal(0);
122-
done();
123-
}
124-
);
125-
});
126-
127-
it('should emit members of an array iterator, and project but raise an error', (done: MochaDone) => {
128-
const expected = [100, 400];
129-
function project(x) {
130-
if (x === 30) {
131-
throw new Error('boom');
132-
} else {
133-
return x * x;
134-
}
135-
}
136-
IteratorObservable.create([10, 20, 30, 40], project)
137-
.subscribe(
138-
(x: number) => {
139-
expect(x).to.equal(expected.shift());
140-
},
141-
(err: any) => {
142-
expect(expected.length).to.equal(0);
143-
expect(err.message).to.equal('boom');
144-
done();
145-
}, () => {
146-
done(new Error('should not be called'));
147-
});
148-
});
149-
15085
it('should emit characters of a string iterator', (done: MochaDone) => {
15186
const expected = ['f', 'o', 'o'];
15287
IteratorObservable.create('foo')
@@ -161,20 +96,6 @@ describe('IteratorObservable', () => {
16196
);
16297
});
16398

164-
it('should emit characters of a string iterator, and project them', (done: MochaDone) => {
165-
const expected = ['F', 'O', 'O'];
166-
IteratorObservable.create('foo', (x: string) => x.toUpperCase())
167-
.subscribe(
168-
(x: string) => { expect(x).to.equal(expected.shift()); },
169-
(x) => {
170-
done(new Error('should not be called'));
171-
}, () => {
172-
expect(expected.length).to.equal(0);
173-
done();
174-
}
175-
);
176-
});
177-
17899
it('should be possible to unsubscribe in the middle of the iteration', (done: MochaDone) => {
179100
const expected = [10, 20, 30];
180101

spec/observables/from-spec.ts

Lines changed: 2 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ describe('Observable.from', () => {
3434
});
3535
});
3636

37-
it('should return T and map for arrays', () => {
37+
it('should return T for arrays', () => {
3838
type(() => {
3939
/* tslint:disable:no-unused-variable */
40-
let o1: Rx.Observable<number> = Observable.from(<number[]>[], x => x.toString(), null, Rx.Scheduler.asap);
40+
let o1: Rx.Observable<number> = Observable.from(<number[]>[], Rx.Scheduler.asap);
4141
/* tslint:enable:no-unused-variable */
4242
});
4343
});
@@ -100,83 +100,5 @@ describe('Observable.from', () => {
100100
);
101101
expect(nextInvoked).to.equal(false);
102102
});
103-
it(`should accept ${source.name} and projection`, (done: MochaDone) => {
104-
let nextInvoked = false;
105-
Observable.from(source.value, x => x + 'x')
106-
.subscribe(
107-
(x: string) => {
108-
nextInvoked = true;
109-
expect(x).to.equal('xx');
110-
},
111-
(x) => {
112-
done(new Error('should not be called'));
113-
},
114-
() => {
115-
expect(nextInvoked).to.equal(true);
116-
done();
117-
}
118-
);
119-
});
120-
it(`should accept ${source.name}, projection and scheduler`, (done: MochaDone) => {
121-
let nextInvoked = false;
122-
Observable.from(source.value, x => x + 'x', Rx.Scheduler.async)
123-
.subscribe(
124-
(x: string) => {
125-
nextInvoked = true;
126-
expect(x).to.equal('xx');
127-
},
128-
(x) => {
129-
done(new Error('should not be called'));
130-
},
131-
() => {
132-
expect(nextInvoked).to.equal(true);
133-
done();
134-
}
135-
);
136-
expect(nextInvoked).to.equal(false);
137-
});
138-
it(`should accept ${source.name}, projection and context`, (done: MochaDone) => {
139-
const projection = function(x) {
140-
expect(this.foo).to.equal('bar');
141-
return x + 'x';
142-
};
143-
let nextInvoked = false;
144-
Observable.from(source.value, projection, { foo: 'bar' })
145-
.subscribe(
146-
(x: string) => {
147-
nextInvoked = true;
148-
expect(x).to.equal('xx');
149-
},
150-
(x) => {
151-
done(new Error('should not be called'));
152-
},
153-
() => {
154-
expect(nextInvoked).to.equal(true);
155-
done();
156-
}
157-
);
158-
});
159-
it(`should accept ${source.name}, projection, context and scheduler`, (done: MochaDone) => {
160-
const projection = function(x) {
161-
expect(this.foo).to.equal('bar');
162-
return x + 'x';
163-
};
164-
let nextInvoked = false;
165-
Observable.from(source.value, projection, { foo: 'bar' }, Rx.Scheduler.async)
166-
.subscribe(
167-
(x: string) => {
168-
nextInvoked = true;
169-
expect(x).to.equal('xx');
170-
},
171-
(x) => {
172-
done(new Error('should not be called'));
173-
},
174-
() => {
175-
expect(nextInvoked).to.equal(true);
176-
done();
177-
}
178-
);
179-
expect(nextInvoked).to.equal(false);
180-
});
181103
}
182104
});

spec/support/default.opts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
--ui spec-js/helpers/testScheduler-ui.js
66

77
--reporter dot
8-
--bail
8+
99
--full-trace
1010
--check-leaks
1111
--globals WebSocket,FormData,XDomainRequest,ActiveXObject

src/observable/ArrayLikeObservable.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,19 @@ import {TeardownLogic} from '../Subscription';
1212
*/
1313
export class ArrayLikeObservable<T> extends Observable<T> {
1414

15-
private mapFn: (x: T, y: number) => T;
16-
17-
static create<T>(arrayLike: ArrayLike<T>, mapFn: (x: T, y: number) => T, thisArg: any, scheduler?: Scheduler): Observable<T> {
15+
static create<T>(arrayLike: ArrayLike<T>, scheduler?: Scheduler): Observable<T> {
1816
const length = arrayLike.length;
1917
if (length === 0) {
2018
return new EmptyObservable<T>();
21-
} else if (length === 1 && !mapFn) {
19+
} else if (length === 1) {
2220
return new ScalarObservable<T>(<any>arrayLike[0], scheduler);
2321
} else {
24-
return new ArrayLikeObservable(arrayLike, mapFn, thisArg, scheduler);
22+
return new ArrayLikeObservable(arrayLike, scheduler);
2523
}
2624
}
2725

2826
static dispatch(state: any) {
29-
const { arrayLike, index, length, mapFn, subscriber } = state;
27+
const { arrayLike, index, length, subscriber } = state;
3028

3129
if (subscriber.closed) {
3230
return;
@@ -37,8 +35,7 @@ export class ArrayLikeObservable<T> extends Observable<T> {
3735
return;
3836
}
3937

40-
const result = mapFn ? mapFn(arrayLike[index], index) : arrayLike[index];
41-
subscriber.next(result);
38+
subscriber.next(arrayLike[index]);
4239

4340
state.index = index + 1;
4441

@@ -48,30 +45,26 @@ export class ArrayLikeObservable<T> extends Observable<T> {
4845
// value used if Array has one value and _isScalar
4946
private value: any;
5047

51-
constructor(private arrayLike: ArrayLike<T>, mapFn: (x: T, y: number) => T, thisArg: any, private scheduler?: Scheduler) {
48+
constructor(private arrayLike: ArrayLike<T>, private scheduler?: Scheduler) {
5249
super();
53-
if (!mapFn && !scheduler && arrayLike.length === 1) {
50+
if (!scheduler && arrayLike.length === 1) {
5451
this._isScalar = true;
5552
this.value = arrayLike[0];
5653
}
57-
if (mapFn) {
58-
this.mapFn = mapFn.bind(thisArg);
59-
}
6054
}
6155

6256
protected _subscribe(subscriber: Subscriber<T>): TeardownLogic {
6357
let index = 0;
64-
const { arrayLike, mapFn, scheduler } = this;
58+
const { arrayLike, scheduler } = this;
6559
const length = arrayLike.length;
6660

6761
if (scheduler) {
6862
return scheduler.schedule(ArrayLikeObservable.dispatch, 0, {
69-
arrayLike, index, length, mapFn, subscriber
63+
arrayLike, index, length, subscriber
7064
});
7165
} else {
7266
for (let i = 0; i < length && !subscriber.closed; i++) {
73-
const result = mapFn ? mapFn(arrayLike[i], i) : arrayLike[i];
74-
subscriber.next(result);
67+
subscriber.next(arrayLike[i]);
7568
}
7669
subscriber.complete();
7770
}

src/observable/ArrayObservable.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export class ArrayObservable<T> extends Observable<T> {
101101
// value used if Array has one value and _isScalar
102102
value: any;
103103

104-
constructor(public array: T[], public scheduler?: Scheduler) {
104+
constructor(private array: T[], private scheduler?: Scheduler) {
105105
super();
106106
if (!scheduler && array.length === 1) {
107107
this._isScalar = true;

src/observable/FromObservable.ts

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import {isArray} from '../util/isArray';
2-
import {isFunction} from '../util/isFunction';
32
import {isPromise} from '../util/isPromise';
4-
import {isScheduler} from '../util/isScheduler';
53
import {PromiseObservable} from './PromiseObservable';
64
import {IteratorObservable} from'./IteratorObservable';
75
import {ArrayObservable} from './ArrayObservable';
@@ -22,12 +20,12 @@ const isArrayLike = (<T>(x: any): x is ArrayLike<T> => x && typeof x.length ===
2220
* @hide true
2321
*/
2422
export class FromObservable<T> extends Observable<T> {
25-
constructor(private ish: ObservableInput<T>, private scheduler: Scheduler) {
23+
constructor(private ish: ObservableInput<T>, private scheduler?: Scheduler) {
2624
super(null);
2725
}
2826

2927
static create<T>(ish: ObservableInput<T>, scheduler?: Scheduler): Observable<T>;
30-
static create<T, R>(ish: ArrayLike<T>, mapFn: (x: any, y: number) => R, thisArg?: any, scheduler?: Scheduler): Observable<R>;
28+
static create<T, R>(ish: ArrayLike<T>, scheduler?: Scheduler): Observable<R>;
3129

3230
/**
3331
* Creates an Observable from an Array, an array-like object, a Promise, an
@@ -71,11 +69,6 @@ export class FromObservable<T> extends Observable<T> {
7169
* @param {ObservableInput<T>} ish A subscribable object, a Promise, an
7270
* Observable-like, an Array, an iterable or an array-like object to be
7371
* converted.
74-
* @param {function(x: any, i: number): T} [mapFn] A "map" function to call
75-
* when converting array-like objects, where `x` is a value from the
76-
* array-like and `i` is the index of that value in the sequence.
77-
* @param {any} [thisArg] The context object to use when calling the `mapFn`,
78-
* if provided.
7972
* @param {Scheduler} [scheduler] The scheduler on which to schedule the
8073
* emissions of values.
8174
* @return {Observable<T>} The Observable whose values are originally from the
@@ -84,19 +77,7 @@ export class FromObservable<T> extends Observable<T> {
8477
* @name from
8578
* @owner Observable
8679
*/
87-
static create<T>(ish: ObservableInput<T>,
88-
mapFnOrScheduler?: Scheduler | ((x: any, y: number) => T),
89-
thisArg?: any,
90-
lastScheduler?: Scheduler): Observable<T> {
91-
let scheduler: Scheduler = null;
92-
let mapFn: (x: any, i: number) => T = null;
93-
if (isFunction(mapFnOrScheduler)) {
94-
scheduler = lastScheduler || null;
95-
mapFn = <(x: any, i: number) => T> mapFnOrScheduler;
96-
} else if (isScheduler(scheduler)) {
97-
scheduler = <Scheduler> mapFnOrScheduler;
98-
}
99-
80+
static create<T>(ish: ObservableInput<T>, scheduler?: Scheduler): Observable<T> {
10081
if (ish != null) {
10182
if (typeof ish[$$observable] === 'function') {
10283
if (ish instanceof Observable && !scheduler) {
@@ -108,9 +89,9 @@ export class FromObservable<T> extends Observable<T> {
10889
} else if (isPromise(ish)) {
10990
return new PromiseObservable<T>(ish, scheduler);
11091
} else if (typeof ish[$$iterator] === 'function' || typeof ish === 'string') {
111-
return new IteratorObservable<T>(<any>ish, null, null, scheduler);
92+
return new IteratorObservable<T>(ish, scheduler);
11293
} else if (isArrayLike(ish)) {
113-
return new ArrayLikeObservable(ish, mapFn, thisArg, scheduler);
94+
return new ArrayLikeObservable(ish, scheduler);
11495
}
11596
}
11697

0 commit comments

Comments
 (0)