Skip to content

Commit 48484a7

Browse files
benleshyyx990803
authored andcommitted
feat(RxJS 6): updated RxJS version 6 (#84)
- Library now uses RxJS directly rather than installing it somehow - Removes a lot of unnecessary null checks - Updates to use pipeable operators - Users using RxJS 5 will need to install rxjs-compat - Updates tests to use RxJS v6 - Adds notes about possible future changes regarding RxJS - Fixes a test relying on synchronous error throwing, that behavior was removed in RxJS 6 due to bugs it could cause. BREAKING CHANGE: RxJS 4 no longer supported BREAKING CHANGE: Rx global no longer required BREAKING CHANGE: RxJS 5 users will need to install rxjs-compat Resolves #83
1 parent 44dfefd commit 48484a7

15 files changed

+1078
-1108
lines changed

package-lock.json

Lines changed: 949 additions & 944 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"rollup": "^0.50.0",
4444
"rollup-plugin-buble": "^0.16.0",
4545
"rollup-watch": "^4.3.1",
46-
"rxjs": "^5.2.0",
46+
"rxjs": "^6.2.0",
4747
"typescript": "^2.5.2",
4848
"vue": "^2.5.0"
4949
},

src/directives/stream.js

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
1-
import { Rx, hasRx, isSubject, warn, getKey, unsub } from '../util'
1+
import { isObserver, warn, getKey } from '../util'
2+
import { fromEvent } from 'rxjs'
23

34
export default {
45
// Example ./example/counter_dir.html
56
bind (el, binding, vnode) {
6-
if (!hasRx()) {
7-
return
8-
}
9-
107
let handle = binding.value
118
const event = binding.arg
129
const streamName = binding.expression
1310
const modifiers = binding.modifiers
1411

15-
if (isSubject(handle)) {
12+
if (isObserver(handle)) {
1613
handle = { subject: handle }
17-
} else if (!handle || !isSubject(handle.subject)) {
14+
} else if (!handle || !isObserver(handle.subject)) {
1815
warn(
1916
'Invalid Subject found in directive with key "' + streamName + '".' +
20-
streamName + ' should be an instance of Rx.Subject or have the ' +
21-
'type { subject: Rx.Subject, data: any }.',
17+
streamName + ' should be an instance of Subject or have the ' +
18+
'type { subject: Subject, data: any }.',
2219
vnode.context
2320
)
2421
return
@@ -45,17 +42,8 @@ export default {
4542
})
4643
})
4744
} else {
48-
if (!Rx.Observable.fromEvent) {
49-
warn(
50-
`No 'fromEvent' method on Observable class. ` +
51-
`v-stream directive requires Rx.Observable.fromEvent method. ` +
52-
`Try import 'rxjs/add/observable/fromEvent' for ${streamName}`,
53-
vnode.context
54-
)
55-
return
56-
}
5745
const fromEventArgs = handle.options ? [el, event, handle.options] : [el, event]
58-
handle.subscription = Rx.Observable.fromEvent(...fromEventArgs).subscribe(e => {
46+
handle.subscription = fromEvent(...fromEventArgs).subscribe(e => {
5947
modifiersExists.forEach(mod => modifiersFuncs[mod](e))
6048
next({
6149
event: e,
@@ -72,7 +60,7 @@ export default {
7260
update (el, binding) {
7361
const handle = binding.value
7462
const _handle = el._rxHandles && el._rxHandles[getKey(binding)]
75-
if (_handle && handle && isSubject(handle.subject)) {
63+
if (_handle && handle && isObserver(handle.subject)) {
7664
_handle.data = handle.data
7765
}
7866
},
@@ -81,7 +69,9 @@ export default {
8169
const key = getKey(binding)
8270
const handle = el._rxHandles && el._rxHandles[key]
8371
if (handle) {
84-
unsub(handle.subscription)
72+
if (handle.subscription) {
73+
handle.subscription.unsubscribe()
74+
}
8575
el._rxHandles[key] = null
8676
}
8777
}

src/methods/createObservableMethod.js

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { Rx, hasRx, warn } from '../util'
1+
import { share } from 'rxjs/operators'
2+
import { Observable } from 'rxjs'
3+
import { warn } from '../util'
24

35
/**
46
* @name Vue.prototype.$createObservableMethod
@@ -8,21 +10,8 @@ import { Rx, hasRx, warn } from '../util'
810
* @return {Observable} Hot stream
911
*/
1012
export default function createObservableMethod (methodName, passContext) {
11-
if (!hasRx()) {
12-
return
13-
}
1413
const vm = this
1514

16-
if (!Rx.Observable.prototype.share) {
17-
warn(
18-
`No 'share' operator. ` +
19-
`$createObservableMethod returns a shared hot observable. ` +
20-
`Try import 'rxjs/add/operator/share' for creating ${methodName}`,
21-
vm
22-
)
23-
return
24-
}
25-
2615
if (vm[methodName] !== undefined) {
2716
warn(
2817
'Potential bug: ' +
@@ -52,5 +41,5 @@ export default function createObservableMethod (methodName, passContext) {
5241
}
5342

5443
// Must be a hot stream otherwise function context may overwrite over and over again
55-
return Rx.Observable.create(creator).share()
44+
return new Observable(creator).pipe(share())
5645
}

src/methods/eventToObservable.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
import { Rx, hasRx } from '../util'
1+
import { Observable } from 'rxjs'
22

33
/**
44
* @see {@link https://vuejs.org/v2/api/#vm-on}
55
* @param {String||Array} evtName Event name
66
* @return {Observable} Event stream
77
*/
88
export default function eventToObservable (evtName) {
9-
if (!hasRx()) {
10-
return
11-
}
129
const vm = this
1310
const evtNames = Array.isArray(evtName) ? evtName : [evtName]
14-
const obs$ = Rx.Observable.create(observer => {
11+
const obs$ = new Observable(observer => {
1512
const eventPairs = evtNames.map(name => {
1613
const callback = msg => observer.next({ name, msg })
1714
vm.$on(name, callback)

src/methods/fromDOMEvent.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import { Rx, hasRx, getDisposable } from '../util'
1+
import { Observable, Subscription, NEVER } from 'rxjs'
22

33
export default function fromDOMEvent (selector, event) {
4-
if (!hasRx()) {
5-
return
6-
}
74
if (typeof window === 'undefined') {
8-
return Rx.Observable.create(() => {})
5+
// TODO(benlesh): I'm not sure if this is really what you want here,
6+
// but it's equivalent to what you were doing. You might want EMPTY
7+
return NEVER
98
}
109

1110
const vm = this
1211
const doc = document.documentElement
13-
const obs$ = Rx.Observable.create(observer => {
12+
const obs$ = new Observable(observer => {
1413
function listener (e) {
1514
if (!vm.$el) return
1615
if (selector === null && vm.$el === e.target) return observer.next(e)
@@ -22,7 +21,7 @@ export default function fromDOMEvent (selector, event) {
2221
}
2322
doc.addEventListener(event, listener)
2423
// Returns function which disconnects the $watch expression
25-
return getDisposable(() => {
24+
return new Subscription(() => {
2625
doc.removeEventListener(event, listener)
2726
})
2827
})

src/methods/subscribeTo.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import { Subscription } from 'rxjs'
2+
13
export default function subscribeTo (observable, next, error, complete) {
2-
var obs$ = observable.subscribe(next, error, complete)
3-
;(this._obSubscriptions || (this._obSubscriptions = [])).push(obs$)
4-
return obs$
4+
const subscription = observable.subscribe(next, error, complete)
5+
;(this._subscription || (this._subscription = new Subscription())).add(subscription)
6+
return subscription
57
}

src/methods/watchAsObservable.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
import { Rx, hasRx, getDisposable } from '../util'
1+
import { Observable, Subscription } from 'rxjs'
22

33
export default function watchAsObservable (expOrFn, options) {
4-
if (!hasRx()) {
5-
return
6-
}
7-
84
const vm = this
9-
const obs$ = Rx.Observable.create(observer => {
5+
const obs$ = new Observable(observer => {
106
let _unwatch
117
const watch = () => {
128
_unwatch = vm.$watch(expOrFn, (newValue, oldValue) => {
@@ -24,7 +20,7 @@ export default function watchAsObservable (expOrFn, options) {
2420
}
2521

2622
// Returns function which disconnects the $watch expression
27-
return getDisposable(() => {
23+
return new Subscription(() => {
2824
_unwatch && _unwatch()
2925
})
3026
})

src/mixin.js

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
import { Rx, defineReactive, isObservable, warn, unsub } from './util'
1+
import { defineReactive, isObservable, warn } from './util'
2+
import { Subject, Subscription } from 'rxjs'
23

34
export default {
45
created () {
56
const vm = this
67
const domStreams = vm.$options.domStreams
78
if (domStreams) {
8-
if (!Rx.Subject) {
9-
warn('Rx.Subject is required to use the "domStreams" option.')
10-
} else {
11-
domStreams.forEach(key => {
12-
vm[key] = new Rx.Subject()
13-
})
14-
}
9+
domStreams.forEach(key => {
10+
vm[key] = new Subject()
11+
})
1512
}
1613

1714
const observableMethods = vm.$options.observableMethods
@@ -33,7 +30,7 @@ export default {
3330
}
3431
if (obs) {
3532
vm.$observables = {}
36-
vm._obSubscriptions = []
33+
vm._subscription = new Subscription()
3734
Object.keys(obs).forEach(key => {
3835
defineReactive(vm, key, undefined)
3936
const ob = vm.$observables[key] = obs[key]
@@ -44,16 +41,16 @@ export default {
4441
)
4542
return
4643
}
47-
vm._obSubscriptions.push(obs[key].subscribe(value => {
44+
vm._subscription.add(obs[key].subscribe(value => {
4845
vm[key] = value
4946
}, (error) => { throw error }))
5047
})
5148
}
5249
},
5350

5451
beforeDestroy () {
55-
if (this._obSubscriptions) {
56-
this._obSubscriptions.forEach(unsub)
52+
if (this._subscription) {
53+
this._subscription.unsubscribe()
5754
}
5855
}
5956
}

src/util.js

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,26 @@
1-
export let Rx
21
export let Vue
32
export let warn = function () {}
43

5-
export function install (_Vue, _Rx) {
6-
Rx = _Rx
4+
// NOTE(benlesh): the value of this method seems dubious now, but I'm not sure
5+
// if this is a Vue convention I'm just not familiar with. Perhaps it would
6+
// be better to just import and use Vue directly?
7+
export function install (_Vue) {
78
Vue = _Vue
89
warn = Vue.util.warn || warn
910
}
1011

11-
export function hasRx (vm) {
12-
if (!Rx) {
13-
warn(
14-
'$watchAsObservable requires Rx to be present globally or ' +
15-
'be passed to Vue.use() as the second argument.',
16-
vm
17-
)
18-
return false
19-
}
20-
return true
21-
}
22-
12+
// TODO(benlesh): as time passes, this should be updated to use RxJS 6.1's
13+
// `isObservable` method. But wait until you're ready to drop support for Rx 5
2314
export function isObservable (ob) {
2415
return ob && typeof ob.subscribe === 'function'
2516
}
2617

27-
export function isSubject (subject) {
18+
export function isObserver (subject) {
2819
return subject && (
29-
typeof subject.next === 'function' ||
30-
typeof subject.onNext === 'function'
20+
typeof subject.next === 'function'
3121
)
3222
}
3323

34-
export function unsub (handle) {
35-
if (!handle) return
36-
if (handle.dispose) {
37-
handle.dispose()
38-
} else if (handle.unsubscribe) {
39-
handle.unsubscribe()
40-
}
41-
}
42-
43-
export function getDisposable (target) {
44-
if (Rx.Subscription) { // Rx5
45-
return new Rx.Subscription(target)
46-
} else { // Rx4
47-
return Rx.Disposable.create(target)
48-
}
49-
}
50-
5124
export function defineReactive (vm, key, val) {
5225
if (key in vm) {
5326
vm[key] = val

0 commit comments

Comments
 (0)