mirror of
https://github.com/AmberGraceRblx/luau-promise.git
synced 2025-04-24 15:50:01 +00:00
parent
3052ec1474
commit
bb13a0e2b6
4 changed files with 267 additions and 2 deletions
|
@ -8,6 +8,8 @@
|
|||
- Improve stack traces
|
||||
- Promise.promisify will now turn errors into rejections even if they occur after a yield.
|
||||
- Add Promise.try
|
||||
- Add `done`, `doneCall`, `doneReturn`
|
||||
- Add `andThenReturn`, `finallyReturn`
|
||||
|
||||
# 2.4.0
|
||||
|
||||
|
|
106
lib/README.md
106
lib/README.md
|
@ -322,6 +322,31 @@ docs:
|
|||
returns: Promise<T>
|
||||
returns: Promise<T>
|
||||
|
||||
- name: done
|
||||
desc: |
|
||||
Set a handler that will be called only if the Promise resolves or is cancelled. This method is similar to `finally`, except it doesn't catch rejections.
|
||||
|
||||
::: warning
|
||||
If this Promise is cancelled, any Promises chained off of it with `andThen` won't run. Only Promises chained with `done` and `finally` will run in the case of cancellation.
|
||||
:::
|
||||
|
||||
Returns a new promise chained from this promise.
|
||||
params:
|
||||
- name: doneHandler
|
||||
type:
|
||||
kind: function
|
||||
params: "status: PromiseStatus"
|
||||
returns: ...any?
|
||||
returns: Promise<...any?>
|
||||
overloads:
|
||||
- params:
|
||||
- name: doneHandler
|
||||
type:
|
||||
kind: function
|
||||
params: "status: PromiseStatus"
|
||||
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.
|
||||
|
@ -364,6 +389,87 @@ docs:
|
|||
desc: Arguments which will be passed to the callback.
|
||||
returns: Promise
|
||||
|
||||
- name: doneCall
|
||||
desc: |
|
||||
Same as `andThenCall`, except for `done`.
|
||||
|
||||
Attaches a `done` 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: andThenReturn
|
||||
desc: |
|
||||
Attaches an `andThen` handler to this Promise that discards the resolved value and returns the given value from it.
|
||||
|
||||
```lua
|
||||
promise:andThenReturn("some", "values")
|
||||
```
|
||||
|
||||
This is sugar for
|
||||
|
||||
```lua
|
||||
promise:andThen(function()
|
||||
return "some", "values"
|
||||
end)
|
||||
```
|
||||
params:
|
||||
- name: "..."
|
||||
type: "...any?"
|
||||
desc: Values to return from the function.
|
||||
returns: Promise<...any?>
|
||||
|
||||
- name: finallyReturn
|
||||
desc: |
|
||||
Attaches a `finally` handler to this Promise that discards the resolved value and returns the given value from it.
|
||||
|
||||
```lua
|
||||
promise:finallyReturn("some", "values")
|
||||
```
|
||||
|
||||
This is sugar for
|
||||
|
||||
```lua
|
||||
promise:finally(function()
|
||||
return "some", "values"
|
||||
end)
|
||||
```
|
||||
params:
|
||||
- name: "..."
|
||||
type: "...any?"
|
||||
desc: Values to return from the function.
|
||||
returns: Promise<...any?>
|
||||
|
||||
- name: doneReturn
|
||||
desc: |
|
||||
Attaches a `done` handler to this Promise that discards the resolved value and returns the given value from it.
|
||||
|
||||
```lua
|
||||
promise:doneReturn("some", "values")
|
||||
```
|
||||
|
||||
This is sugar for
|
||||
|
||||
```lua
|
||||
promise:done(function()
|
||||
return "some", "values"
|
||||
end)
|
||||
```
|
||||
|
||||
params:
|
||||
- name: "..."
|
||||
type: "...any?"
|
||||
desc: Values to return from the function.
|
||||
returns: Promise<...any?>
|
||||
|
||||
|
||||
- name: cancel
|
||||
desc: |
|
||||
Cancels this promise, preventing the promise from resolving or rejecting. Does not do anything if the promise is already settled.
|
||||
|
|
69
lib/init.lua
69
lib/init.lua
|
@ -502,6 +502,16 @@ function Promise.prototype:andThenCall(callback, ...)
|
|||
end)
|
||||
end
|
||||
|
||||
--[[
|
||||
Shorthand for an andThen handler that returns the given value.
|
||||
]]
|
||||
function Promise.prototype:andThenReturn(...)
|
||||
local length, values = pack(...)
|
||||
return self:_andThen(debug.traceback(), function()
|
||||
return unpack(values, 1, length)
|
||||
end)
|
||||
end
|
||||
|
||||
--[[
|
||||
Cancels the promise, disallowing it from rejecting or resolving, and calls
|
||||
the cancellation hook if provided.
|
||||
|
@ -548,8 +558,10 @@ end
|
|||
Used to set a handler for when the promise resolves, rejects, or is
|
||||
cancelled. Returns a new promise chained from this promise.
|
||||
]]
|
||||
function Promise.prototype:_finally(traceback, finallyHandler)
|
||||
self._unhandledRejection = false
|
||||
function Promise.prototype:_finally(traceback, finallyHandler, onlyOk)
|
||||
if not onlyOk then
|
||||
self._unhandledRejection = false
|
||||
end
|
||||
|
||||
-- Return a promise chained off of this promise
|
||||
return Promise._new(traceback, function(resolve, reject)
|
||||
|
@ -563,6 +575,17 @@ function Promise.prototype:_finally(traceback, finallyHandler)
|
|||
)
|
||||
end
|
||||
|
||||
if onlyOk then
|
||||
local callback = finallyCallback
|
||||
finallyCallback = function(...)
|
||||
if self._status == Promise.Status.Rejected then
|
||||
return resolve(self)
|
||||
end
|
||||
|
||||
return callback(...)
|
||||
end
|
||||
end
|
||||
|
||||
if self._status == Promise.Status.Started then
|
||||
-- The promise is not settled, so queue this.
|
||||
table.insert(self._queuedFinally, finallyCallback)
|
||||
|
@ -592,6 +615,48 @@ function Promise.prototype:finallyCall(callback, ...)
|
|||
end)
|
||||
end
|
||||
|
||||
--[[
|
||||
Shorthand for a finally handler that returns the given value.
|
||||
]]
|
||||
function Promise.prototype:finallyReturn(...)
|
||||
local length, values = pack(...)
|
||||
return self:_finally(debug.traceback(), function()
|
||||
return unpack(values, 1, length)
|
||||
end)
|
||||
end
|
||||
|
||||
--[[
|
||||
Similar to finally, except rejections are propagated through it.
|
||||
]]
|
||||
function Promise.prototype:done(finallyHandler)
|
||||
assert(
|
||||
finallyHandler == nil or type(finallyHandler) == "function",
|
||||
ERROR_NON_FUNCTION:format("Promise:finallyO")
|
||||
)
|
||||
return self:_finally(debug.traceback(), finallyHandler, true)
|
||||
end
|
||||
|
||||
--[[
|
||||
Calls a callback on `done` with specific arguments.
|
||||
]]
|
||||
function Promise.prototype:doneCall(callback, ...)
|
||||
assert(type(callback) == "function", ERROR_NON_FUNCTION:format("Promise:doneCall"))
|
||||
local length, values = pack(...)
|
||||
return self:_finally(debug.traceback(), function()
|
||||
return callback(unpack(values, 1, length))
|
||||
end, true)
|
||||
end
|
||||
|
||||
--[[
|
||||
Shorthand for a done handler that returns the given value.
|
||||
]]
|
||||
function Promise.prototype:doneReturn(...)
|
||||
local length, values = pack(...)
|
||||
return self:_finally(debug.traceback(), function()
|
||||
return unpack(values, 1, length)
|
||||
end, true)
|
||||
end
|
||||
|
||||
--[[
|
||||
Yield until the promise is completed.
|
||||
|
||||
|
|
|
@ -416,6 +416,18 @@ return function()
|
|||
expect(p2._parent).to.equal(p1)
|
||||
expect(p1._consumers[p2]).to.equal(true)
|
||||
end)
|
||||
|
||||
it("should forward return values", function()
|
||||
local value
|
||||
|
||||
Promise.resolve():finally(function()
|
||||
return 1
|
||||
end):andThen(function(v)
|
||||
value = v
|
||||
end)
|
||||
|
||||
expect(value).to.equal(1)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("Promise.all", function()
|
||||
|
@ -698,4 +710,84 @@ return function()
|
|||
expect(errorText:find("errortext")).to.be.ok()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("Promise:andThenReturn", function()
|
||||
it("should return the given values", function()
|
||||
local value1, value2
|
||||
|
||||
Promise.resolve():andThenReturn(1, 2):andThen(function(one, two)
|
||||
value1 = one
|
||||
value2 = two
|
||||
end)
|
||||
|
||||
expect(value1).to.equal(1)
|
||||
expect(value2).to.equal(2)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("Promise:doneReturn", function()
|
||||
it("should return the given values", function()
|
||||
local value1, value2
|
||||
|
||||
Promise.resolve():doneReturn(1, 2):andThen(function(one, two)
|
||||
value1 = one
|
||||
value2 = two
|
||||
end)
|
||||
|
||||
expect(value1).to.equal(1)
|
||||
expect(value2).to.equal(2)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("Promise:andThenCall", function()
|
||||
it("should call the given function with arguments", function()
|
||||
local value1, value2
|
||||
Promise.resolve():andThenCall(function(a, b)
|
||||
value1 = a
|
||||
value2 = b
|
||||
end, 3, 4)
|
||||
|
||||
expect(value1).to.equal(3)
|
||||
expect(value2).to.equal(4)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("Promise:doneCall", function()
|
||||
it("should call the given function with arguments", function()
|
||||
local value1, value2
|
||||
Promise.resolve():doneCall(function(a, b)
|
||||
value1 = a
|
||||
value2 = b
|
||||
end, 3, 4)
|
||||
|
||||
expect(value1).to.equal(3)
|
||||
expect(value2).to.equal(4)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("Promise:done", function()
|
||||
it("should trigger on resolve or cancel", function()
|
||||
local promise = Promise.new(function() end)
|
||||
local value
|
||||
|
||||
local p = promise:done(function()
|
||||
value = true
|
||||
end)
|
||||
|
||||
expect(value).to.never.be.ok()
|
||||
promise:cancel()
|
||||
expect(p:getStatus()).to.equal(Promise.Status.Cancelled)
|
||||
expect(value).to.equal(true)
|
||||
|
||||
local never, always
|
||||
Promise.reject():done(function()
|
||||
never = true
|
||||
end):finally(function()
|
||||
always = true
|
||||
end)
|
||||
|
||||
expect(never).to.never.be.ok()
|
||||
expect(always).to.be.ok()
|
||||
end)
|
||||
end)
|
||||
end
|
Loading…
Reference in a new issue