Add calls, awaitValue

This commit is contained in:
Eryn Lynn 2019-09-12 20:13:29 -04:00
parent 3d53e7a364
commit 783eb1c2bb
4 changed files with 122 additions and 32 deletions

View file

@ -1,3 +1,8 @@
# 2.1.0
- Add `finallyCall`, `andThenCall`
- Add `awaitValue`
# 2.0.0 # 2.0.0
- Add Promise.race - Add Promise.race

View file

@ -52,7 +52,7 @@ end
## Cancellable animation sequence ## Cancellable animation sequence
The following is an example of an animation sequence which is composable and cancellable. If the sequence is cancelled, the animated part will instantly jump to the end position as if it had played all the way through. The following is an example of an animation sequence which is composable and cancellable. If the sequence is cancelled, the animated part will instantly jump to the end position as if it had played all the way through.
We use `finally` instead of `andThen` because we want the Promises to run even if the Promise is cancelled. We handle the case of the Promise being cancelled with the `onCancel` function. We use <ApiLink to="Promise.finallyCall" />, which uses `finally` internally, instead of `andThen` because we want the Promises to run even if the Promise is cancelled. We handle the case of the Promise being cancelled with the `onCancel` function.
We take advantage of Promise chaining by returning Promises from the `finally` handler functions. Because of this behavior, cancelling the final Promise in the chain will propagate up to the very top and cancel every single Promise you see here. We take advantage of Promise chaining by returning Promises from the `finally` handler functions. Because of this behavior, cancelling the final Promise in the chain will propagate up to the very top and cancel every single Promise you see here.
@ -69,42 +69,38 @@ local function apply(obj, props)
end end
local function runTween(obj, props) local function runTween(obj, props)
return function() return Promise.new(function(resolve, reject, onCancel)
return Promise.new(function(resolve, reject, onCancel) local tween = TweenService:Create(obj, TweenInfo.new(0.5), props)
local tween = TweenService:Create(obj, TweenInfo.new(0.5), props)
if onCancel(function() if onCancel(function()
tween:Cancel() tween:Cancel()
apply(obj, props) apply(obj, props)
end) then return end end) then return end
tween.Completed:Connect(resolve) tween.Completed:Connect(resolve)
tween:Play() tween:Play()
end) end)
end
end end
local function runAnimation(part, intensity) local function runAnimation(part, intensity)
return function() return Promise.resolve()
return Promise.resolve() :finallyCall(sleep, 1))
:finally(sleep(1)) :finallyCall(runTween, part, {
:finally(runTween(part, { Reflectance = 1 * intensity
Reflectance = 1 * intensity }):finallyCall(runTween, part, {
})):finally(runTween(part, { CFrame = CFrame.new(part.Position) *
CFrame = CFrame.new(part.Position) * CFrame.Angles(0, math.rad(90 * intensity), 0)
CFrame.Angles(0, math.rad(90 * intensity), 0) }):finallyCall(runTween, part, {
})):finally(runTween(part, { Size = (
Size = ( Vector3.new(10, 10, 10) * intensity
Vector3.new(10, 10, 10) * intensity ) + Vector3.new(1, 1, 1)
) + Vector3.new(1, 1, 1) })
}))
end
end end
local animation = Promise.resolve() -- Begin Promise chain local animation = Promise.resolve() -- Begin Promise chain
:finally(runAnimation(workspace.Part, 1)) :finallyCall(runAnimation, workspace.Part, 1)
:finally(sleep(1)) :finallyCall(sleep, 1)
:finally(runAnimation(workspace.Part, 0)) :finallyCall(runAnimation, workspace.Part, 0)
wait(2) wait(2)
animation:cancel() -- Remove this line to see the full animation animation:cancel() -- Remove this line to see the full animation

View file

@ -261,7 +261,47 @@ docs:
returns: Promise<T> returns: Promise<T>
returns: Promise<T> returns: Promise<T>
- name: andThenCall
desc: |
Attaches an `andThen` handler to this Promise that calls the given callback with the predefined arguments. The resolved value is discarded.
```lua
promise:andThenCall(someFunction, "some", "arguments")
```
This is sugar for
```lua
promise:andThen(function()
return callback(...args)
end)
```
params:
- name: callback
type:
kind: function
params: "...: ...any?"
returns: "any"
- name: "..."
type: "...any?"
desc: Arguments which will be passed to the callback.
returns: Promise
- name: finallyCall
desc: |
Same as `andThenCall`, except for `finally`.
Attaches a `finally` handler to this Promise that calls the given callback with the predefined arguments.
params:
- name: callback
type:
kind: function
params: "...: ...any?"
returns: "any"
- name: "..."
type: "...any?"
desc: Arguments which will be passed to the callback.
returns: Promise
- name: cancel - name: cancel
desc: | desc: |
@ -272,7 +312,12 @@ docs:
Promises will only be cancelled if all of their consumers are also cancelled. This is to say that if you call `andThen` twice on the same promise, and you cancel only one of the child promises, it will not cancel the parent promise until the other child promise is also cancelled. Promises will only be cancelled if all of their consumers are also cancelled. This is to say that if you call `andThen` twice on the same promise, and you cancel only one of the child promises, it will not cancel the parent promise until the other child promise is also cancelled.
- name: await - name: await
desc: Yields the current thread until the given Promise completes. Returns true if the Promise resolved, followed by the values that the promise resolved or rejected with. desc: |
Yields the current thread until the given Promise completes. Returns true if the Promise resolved, followed by the values that the promise resolved or rejected with.
::: warning
If the Promise gets cancelled, this function will return `false`, which is indistinguishable from a rejection. If you need to differentiate, you should use [[Promise.awaitStatus]] instead.
:::
returns: returns:
- desc: "`true` if the Promise successfully resolved." - desc: "`true` if the Promise successfully resolved."
type: boolean type: boolean
@ -286,6 +331,14 @@ docs:
desc: The Promise's status. desc: The Promise's status.
- type: ...any? - type: ...any?
desc: The values that the Promise resolved or rejected with. desc: The values that the Promise resolved or rejected with.
- name: awaitValue
desc: |
Yields the current thread until the given Promise completes. Returns the the values that the promise resolved with.
Errors if the Promise rejects or gets cancelled.
returns:
- type: ...any?
desc: The values that the Promise resolved with.
- name: getStatus - name: getStatus
desc: Returns the current Promise status. desc: Returns the current Promise status.

View file

@ -400,6 +400,16 @@ function Promise.prototype:catch(failureCallback)
return self:andThen(nil, failureCallback) return self:andThen(nil, failureCallback)
end end
--[[
Calls a callback on `andThen` with specific arguments.
]]
function Promise.prototype:andThenCall(callback, ...)
local length, values = pack(...)
return self:andThen(function()
return callback(unpack(values, 1, length))
end)
end
--[[ --[[
Cancels the promise, disallowing it from rejecting or resolving, and calls Cancels the promise, disallowing it from rejecting or resolving, and calls
the cancellation hook if provided. the cancellation hook if provided.
@ -466,6 +476,16 @@ function Promise.prototype:finally(finallyHandler)
end, self) end, self)
end end
--[[
Calls a callback on `finally` with specific arguments.
]]
function Promise.prototype:finallyCall(callback, ...)
local length, values = pack(...)
return self:finally(function()
return callback(unpack(values, 1, length))
end)
end
--[[ --[[
Yield until the promise is completed. Yield until the promise is completed.
@ -504,6 +524,22 @@ function Promise.prototype:await(...)
return status == Promise.Status.Resolved, unpack(result, 1, length - 1) return status == Promise.Status.Resolved, unpack(result, 1, length - 1)
end end
--[[
Calls await and only returns if the Promise resolves.
Throws if the Promise rejects or gets cancelled.
]]
function Promise.prototype:awaitValue(...)
local length, result = pack(self:awaitStatus(...))
local status = table.remove(result, 1)
assert(
status == Promise.Status.Resolved,
tostring(result[1] == nil and "" or result[1])
)
return unpack(result, 1, length - 1)
end
--[[ --[[
Intended for use in tests. Intended for use in tests.