|
@@ -10,6 +10,9 @@ util.eq = function(x, y) return x == y end
|
|
util.noop = function() end
|
|
util.noop = function() end
|
|
util.identity = function(x) return x end
|
|
util.identity = function(x) return x end
|
|
util.constant = function(x) return function() return x end end
|
|
util.constant = function(x) return function() return x end end
|
|
|
|
+util.isa = function(object, class)
|
|
|
|
+ return type(object) == 'table' and getmetatable(object).__index == class
|
|
|
|
+end
|
|
|
|
|
|
--- @class Subscription
|
|
--- @class Subscription
|
|
-- @description A handle representing the link between an Observer and an Observable, as well as any
|
|
-- @description A handle representing the link between an Observer and an Observable, as well as any
|
|
@@ -1735,7 +1738,7 @@ end
|
|
function Subject:subscribe(onNext, onError, onCompleted)
|
|
function Subject:subscribe(onNext, onError, onCompleted)
|
|
local observer
|
|
local observer
|
|
|
|
|
|
- if type(onNext) == 'table' then
|
|
|
|
|
|
+ if util.isa(onNext, Observer) then
|
|
observer = onNext
|
|
observer = onNext
|
|
else
|
|
else
|
|
observer = Observer.create(onNext, onError, onCompleted)
|
|
observer = Observer.create(onNext, onError, onCompleted)
|
|
@@ -1788,6 +1791,103 @@ end
|
|
|
|
|
|
Subject.__call = Subject.onNext
|
|
Subject.__call = Subject.onNext
|
|
|
|
|
|
|
|
+--- @class AsyncSubject
|
|
|
|
+-- @description AsyncSubjects are subjects that produce either no values or a single value. If
|
|
|
|
+-- multiple values are produced via onNext, only the last one is used. If onError is called, then
|
|
|
|
+-- no value is produced and onError is called on any subscribed Observers. If an Observer
|
|
|
|
+-- subscribes and the AsyncSubject has already terminated, the Observer will immediately receive the
|
|
|
|
+-- value or the error.
|
|
|
|
+local AsyncSubject = setmetatable({}, Observable)
|
|
|
|
+AsyncSubject.__index = AsyncSubject
|
|
|
|
+AsyncSubject.__tostring = util.constant('AsyncSubject')
|
|
|
|
+
|
|
|
|
+--- Creates a new AsyncSubject.
|
|
|
|
+-- @returns {AsyncSubject}
|
|
|
|
+function AsyncSubject.create()
|
|
|
|
+ local self = {
|
|
|
|
+ observers = {},
|
|
|
|
+ stopped = false,
|
|
|
|
+ value = nil,
|
|
|
|
+ errorMessage = nil
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return setmetatable(self, AsyncSubject)
|
|
|
|
+end
|
|
|
|
+
|
|
|
|
+--- Creates a new Observer and attaches it to the AsyncSubject.
|
|
|
|
+-- @arg {function|table} onNext|observer - A function called when the AsyncSubject produces a value
|
|
|
|
+-- or an existing Observer to attach to the AsyncSubject.
|
|
|
|
+-- @arg {function} onError - Called when the AsyncSubject terminates due to an error.
|
|
|
|
+-- @arg {function} onCompleted - Called when the AsyncSubject completes normally.
|
|
|
|
+function AsyncSubject:subscribe(onNext, onError, onCompleted)
|
|
|
|
+ local observer
|
|
|
|
+
|
|
|
|
+ if util.isa(onNext, Observer) then
|
|
|
|
+ observer = onNext
|
|
|
|
+ else
|
|
|
|
+ observer = Observer.create(onNext, onError, onCompleted)
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ if self.value then
|
|
|
|
+ observer:onNext(util.unpack(self.value))
|
|
|
|
+ observer:onCompleted()
|
|
|
|
+ return
|
|
|
|
+ elseif self.errorMessage then
|
|
|
|
+ observer:onError(self.errorMessage)
|
|
|
|
+ return
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ table.insert(self.observers, observer)
|
|
|
|
+
|
|
|
|
+ return Subscription.create(function()
|
|
|
|
+ for i = 1, #self.observers do
|
|
|
|
+ if self.observers[i] == observer then
|
|
|
|
+ table.remove(self.observers, i)
|
|
|
|
+ return
|
|
|
|
+ end
|
|
|
|
+ end
|
|
|
|
+ end)
|
|
|
|
+end
|
|
|
|
+
|
|
|
|
+--- Pushes zero or more values to the AsyncSubject.
|
|
|
|
+-- @arg {*...} values
|
|
|
|
+function AsyncSubject:onNext(...)
|
|
|
|
+ if not self.stopped then
|
|
|
|
+ self.value = util.pack(...)
|
|
|
|
+ end
|
|
|
|
+end
|
|
|
|
+
|
|
|
|
+--- Signal to all Observers that an error has occurred.
|
|
|
|
+-- @arg {string=} message - A string describing what went wrong.
|
|
|
|
+function AsyncSubject:onError(message)
|
|
|
|
+ if not self.stopped then
|
|
|
|
+ self.errorMessage = message
|
|
|
|
+
|
|
|
|
+ for i = 1, #self.observers do
|
|
|
|
+ self.observers[i]:onError(self.errorMessage)
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ self.stopped = true
|
|
|
|
+ end
|
|
|
|
+end
|
|
|
|
+
|
|
|
|
+--- Signal to all Observers that the AsyncSubject will not produce any more values.
|
|
|
|
+function AsyncSubject:onCompleted()
|
|
|
|
+ if not self.stopped then
|
|
|
|
+ for i = 1, #self.observers do
|
|
|
|
+ if self.value then
|
|
|
|
+ self.observers[i]:onNext(util.unpack(self.value))
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ self.observers[i]:onCompleted()
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ self.stopped = true
|
|
|
|
+ end
|
|
|
|
+end
|
|
|
|
+
|
|
|
|
+AsyncSubject.__call = AsyncSubject.onNext
|
|
|
|
+
|
|
--- @class BehaviorSubject
|
|
--- @class BehaviorSubject
|
|
-- @description A Subject that tracks its current value. Provides an accessor to retrieve the most
|
|
-- @description A Subject that tracks its current value. Provides an accessor to retrieve the most
|
|
-- recent pushed value, and all subscribers immediately receive the latest value.
|
|
-- recent pushed value, and all subscribers immediately receive the latest value.
|
|
@@ -1817,8 +1917,16 @@ end
|
|
-- @arg {function} onError - Called when the Subject terminates due to an error.
|
|
-- @arg {function} onError - Called when the Subject terminates due to an error.
|
|
-- @arg {function} onCompleted - Called when the Subject completes normally.
|
|
-- @arg {function} onCompleted - Called when the Subject completes normally.
|
|
function BehaviorSubject:subscribe(onNext, onError, onCompleted)
|
|
function BehaviorSubject:subscribe(onNext, onError, onCompleted)
|
|
- local observer = Observer.create(onNext, onError, onCompleted)
|
|
|
|
|
|
+ local observer
|
|
|
|
+
|
|
|
|
+ if util.isa(onNext, Observer) then
|
|
|
|
+ observer = onNext
|
|
|
|
+ else
|
|
|
|
+ observer = Observer.create(onNext, onError, onCompleted)
|
|
|
|
+ end
|
|
|
|
+
|
|
Subject.subscribe(self, observer)
|
|
Subject.subscribe(self, observer)
|
|
|
|
+
|
|
if self.value then
|
|
if self.value then
|
|
observer:onNext(unpack(self.value))
|
|
observer:onNext(unpack(self.value))
|
|
end
|
|
end
|
|
@@ -1849,5 +1957,6 @@ return {
|
|
ImmediateScheduler = ImmediateScheduler,
|
|
ImmediateScheduler = ImmediateScheduler,
|
|
CooperativeScheduler = CooperativeScheduler,
|
|
CooperativeScheduler = CooperativeScheduler,
|
|
Subject = Subject,
|
|
Subject = Subject,
|
|
|
|
+ AsyncSubject = AsyncSubject,
|
|
BehaviorSubject = BehaviorSubject
|
|
BehaviorSubject = BehaviorSubject
|
|
}
|
|
}
|