mirror of
https://github.com/AmberGraceRblx/luau-promise.git
synced 2025-04-24 15:50:01 +00:00
parent
e5843cf5a2
commit
b4ba6d2414
3 changed files with 122 additions and 0 deletions
|
@ -369,6 +369,48 @@ docs:
|
|||
returns: Promise<T>
|
||||
static: true
|
||||
|
||||
- name: fromEvent
|
||||
desc: |
|
||||
Converts an event into a Promise which resolves the next time the event fires.
|
||||
|
||||
The optional `predicate` callback, if passed, will receive the event arguments and should return `true` or `false`, based on if this fired event should resolve the Promise or not. If `true`, the Promise resolves. If `false`, nothing happens and the predicate will be rerun the next time the event fires.
|
||||
|
||||
The Promise will resolve with the event arguments.
|
||||
|
||||
::: tip
|
||||
This function will work given any object with a `Connect` method. This includes all Roblox events.
|
||||
:::
|
||||
|
||||
```lua
|
||||
-- Creates a Promise which only resolves when `somePart` is touched by a part named `"Something specific"`.
|
||||
return Promise.fromEvent(somePart.Touched, function(part)
|
||||
return part.Name == "Something specific"
|
||||
end)
|
||||
```
|
||||
params:
|
||||
- name: event
|
||||
type:
|
||||
kind: interface
|
||||
type:
|
||||
Connect:
|
||||
type:
|
||||
kind: function
|
||||
params:
|
||||
- name: callback
|
||||
type:
|
||||
kind: function
|
||||
params: "...: P"
|
||||
desc: Any object with a `Connect` method. This includes all Roblox events.
|
||||
- name: predicate
|
||||
optional: true
|
||||
type:
|
||||
kind: function
|
||||
params: "...: P"
|
||||
returns: boolean
|
||||
desc: A function which determines if the Promise should resolve with the given value, or wait for the next event to check again.
|
||||
returns: Promise<P>
|
||||
static: true
|
||||
|
||||
- name: is
|
||||
desc: Checks whether the given object is a Promise via duck typing. This only checks if the object is a table and has an `andThen` method.
|
||||
static: true
|
||||
|
|
47
lib/init.lua
47
lib/init.lua
|
@ -1341,4 +1341,51 @@ function Promise.retry(callback, times, ...)
|
|||
end)
|
||||
end
|
||||
|
||||
--[[
|
||||
Converts an event into a Promise with an optional predicate
|
||||
]]
|
||||
function Promise.fromEvent(event, predicate)
|
||||
predicate = predicate or function()
|
||||
return true
|
||||
end
|
||||
|
||||
return Promise._new(debug.traceback(nil, 2), function(resolve, reject, onCancel)
|
||||
local connection
|
||||
local shouldDisconnect = false
|
||||
|
||||
local function disconnect()
|
||||
connection:Disconnect()
|
||||
connection = nil
|
||||
end
|
||||
|
||||
-- We use shouldDisconnect because if the callback given to Connect is called before
|
||||
-- Connect returns, connection will still be nil. This happens with events that queue up
|
||||
-- events when there's nothing connected, such as RemoteEvents
|
||||
|
||||
connection = event:Connect(function(...)
|
||||
local callbackValue = predicate(...)
|
||||
|
||||
if callbackValue == true then
|
||||
resolve(...)
|
||||
|
||||
if connection then
|
||||
disconnect()
|
||||
else
|
||||
shouldDisconnect = true
|
||||
end
|
||||
elseif type(callbackValue) ~= "boolean" then
|
||||
error("Promise.fromEvent predicate should always return a boolean")
|
||||
end
|
||||
end)
|
||||
|
||||
if shouldDisconnect and connection then
|
||||
return disconnect()
|
||||
end
|
||||
|
||||
onCancel(function()
|
||||
disconnect()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
return Promise
|
||||
|
|
|
@ -1441,4 +1441,37 @@ return function()
|
|||
end)
|
||||
end)
|
||||
|
||||
describe("Promise.fromEvent", function()
|
||||
it("should convert a Promise into an event", function()
|
||||
local event = Instance.new("BindableEvent")
|
||||
|
||||
local promise = Promise.fromEvent(event.Event)
|
||||
|
||||
expect(promise:getStatus()).to.equal(Promise.Status.Started)
|
||||
|
||||
event:Fire("foo")
|
||||
|
||||
expect(promise:getStatus()).to.equal(Promise.Status.Resolved)
|
||||
expect(promise._values[1]).to.equal("foo")
|
||||
end)
|
||||
|
||||
it("should convert a Promise into an event with the predicate", function()
|
||||
local event = Instance.new("BindableEvent")
|
||||
|
||||
local promise = Promise.fromEvent(event.Event, function(param)
|
||||
return param == "foo"
|
||||
end)
|
||||
|
||||
expect(promise:getStatus()).to.equal(Promise.Status.Started)
|
||||
|
||||
event:Fire("bar")
|
||||
|
||||
expect(promise:getStatus()).to.equal(Promise.Status.Started)
|
||||
|
||||
event:Fire("foo")
|
||||
|
||||
expect(promise:getStatus()).to.equal(Promise.Status.Resolved)
|
||||
expect(promise._values[1]).to.equal("foo")
|
||||
end)
|
||||
end)
|
||||
end
|
Loading…
Reference in a new issue