Add Promise:tap

This commit is contained in:
Eryn Lynn 2019-09-28 01:33:06 -04:00
parent 1ca7dfbc3e
commit 4829a421db
3 changed files with 83 additions and 0 deletions

View file

@ -246,6 +246,27 @@ docs:
params: "...: ...any?"
returns: Promise<T>
returns: Promise<T>
- name: tap
desc: |
Similar to [[Promise.andThen]], except the return value is the same as the value passed to the handler. In other words, you can insert a `:tap` into a Promise chain without affecting the value that downstream Promises receive.
```lua
getTheValue()
:tap(print)
:andThen(function(theValue)
print("Got", theValue, "even though print returns nil!")
end)
```
If you return a Promise from the tap handler callback, its value will be discarded but `tap` will still wait until it resolves before passing the original value through.
params:
- name: tapHandler
type:
kind: function
params: "...: ...any?"
returns: ...any?
returns: Promise<...any?>
- name: finally
desc: |

View file

@ -401,6 +401,25 @@ function Promise.prototype:catch(failureCallback)
return self:andThen(nil, failureCallback)
end
--[[
Like andThen, but the value passed into the handler is also the
value returned from the handler.
]]
function Promise.prototype:tap(tapCallback)
return self:andThen(function(...)
local callbackReturn = tapCallback(...)
if Promise.is(callbackReturn) then
local length, values = pack(...)
return callbackReturn:andThen(function()
return unpack(values, 1, length)
end)
end
return ...
end)
end
--[[
Calls a callback on `andThen` with specific arguments.
]]

View file

@ -617,4 +617,47 @@ return function()
expect(result).to.equal(2)
end)
end)
describe("Promise.tap", function()
it("should thread through values", function()
local first, second
Promise.resolve(1)
:andThen(function(v)
return v + 1
end)
:tap(function(v)
first = v
return v + 1
end)
:andThen(function(v)
second = v
end)
expect(first).to.equal(2)
expect(second).to.equal(2)
end)
it("should chain onto promises", function()
local resolveInner, finalValue
local promise = Promise.resolve(1)
:tap(function()
return Promise.new(function(resolve)
resolveInner = resolve
end)
end)
:andThen(function(v)
finalValue = v
end)
expect(promise:getStatus()).to.equal(Promise.Status.Started)
expect(finalValue).to.never.be.ok()
resolveInner(1)
expect(promise:getStatus()).to.equal(Promise.Status.Resolved)
expect(finalValue).to.equal(1)
end)
end)
end