Browse Source

Observable.defer;

bjorn 9 years ago
parent
commit
1fccdefeb6
4 changed files with 71 additions and 0 deletions
  1. 11 0
      doc/README.md
  2. 12 0
      rx.lua
  3. 12 0
      src/observable.lua
  4. 36 0
      tests/observable.lua

+ 11 - 0
doc/README.md

@@ -19,6 +19,7 @@ RxLua
   - [fromRange](#fromrangeinitial-limit-step)
   - [fromTable](#fromtabletable-iterator-keys)
   - [fromCoroutine](#fromcoroutinecoroutine)
+  - [defer](#deferfactory)
   - [dump](#dumpname-formatter)
   - [all](#allpredicate)
   - [amb](#ambobservables)
@@ -231,6 +232,16 @@ Creates an Observable that produces values when the specified coroutine yields.
 
 ---
 
+#### `.defer(factory)`
+
+Creates an Observable that creates a new Observable for each observer using a factory function.
+
+| Name | Type | Default | Description |
+|------|------|---------|-------------|
+| `factory` | function |  | A function that returns an Observable. |
+
+---
+
 #### `:dump(name, formatter)`
 
 Subscribes to this Observable and prints values it produces.

+ 12 - 0
rx.lua

@@ -207,6 +207,18 @@ function Observable.fromCoroutine(thread, scheduler)
   end)
 end
 
+--- Creates an Observable that creates a new Observable for each observer using a factory function.
+-- @arg {function} factory - A function that returns an Observable.
+-- @returns {Observable}
+function Observable.defer(fn)
+  return setmetatable({
+    subscribe = function(_, ...)
+      local observable = fn()
+      return observable:subscribe(...)
+    end
+  }, Observable)
+end
+
 --- Subscribes to this Observable and prints values it produces.
 -- @arg {string=} name - Prefixes the printed messages with a name.
 -- @arg {function=tostring} formatter - A function that formats one or more values to be printed.

+ 12 - 0
src/observable.lua

@@ -122,6 +122,18 @@ function Observable.fromCoroutine(thread, scheduler)
   end)
 end
 
+--- Creates an Observable that creates a new Observable for each observer using a factory function.
+-- @arg {function} factory - A function that returns an Observable.
+-- @returns {Observable}
+function Observable.defer(fn)
+  return setmetatable({
+    subscribe = function(_, ...)
+      local observable = fn()
+      return observable:subscribe(...)
+    end
+  }, Observable)
+end
+
 --- Subscribes to this Observable and prints values it produces.
 -- @arg {string=} name - Prefixes the printed messages with a name.
 -- @arg {function=tostring} formatter - A function that formats one or more values to be printed.

+ 36 - 0
tests/observable.lua

@@ -174,6 +174,42 @@ describe('Observable', function()
     end)
   end)
 
+  describe('defer', function()
+    it('returns an Observable', function()
+      expect(Rx.Observable.defer()).to.be.an(Rx.Observable)
+    end)
+
+    it('fails if no factory is specified', function()
+      expect(Rx.Observable.defer().subscribe).to.fail()
+    end)
+
+    it('fails if the factory does not return an Observable', function()
+      expect(Rx.Observable.defer(function() return nil end).subscribe).to.fail()
+    end)
+
+    it('uses the factory function to create a new Observable for each subscriber', function()
+      local i = 0
+      local function factory()
+        i = i + 1
+        return Rx.Observable.fromRange(i, 3)
+      end
+      expect(Rx.Observable.defer(factory)).to.produce(1, 2, 3)
+      expect(Rx.Observable.defer(factory)).to.produce(2, 3)
+      expect(Rx.Observable.defer(factory)).to.produce(3)
+    end)
+
+    it('returns Observables that return subscriptions from their subscribe function', function()
+      local subscription = Rx.Subscription.create()
+      local function factory()
+        return Rx.Observable.create(function()
+          return subscription
+        end)
+      end
+
+      expect(Rx.Observable.defer(factory):subscribe()).to.equal(subscription)
+    end)
+  end)
+
   describe('dump', function()
   end)