mirror of
https://github.com/AmberGraceRblx/luau-promise.git
synced 2025-04-25 08:00:03 +00:00
parent
e5843cf5a2
commit
b4ba6d2414
3 changed files with 122 additions and 0 deletions
|
@ -369,6 +369,48 @@ docs:
|
||||||
returns: Promise<T>
|
returns: Promise<T>
|
||||||
static: true
|
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
|
- 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.
|
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
|
static: true
|
||||||
|
|
47
lib/init.lua
47
lib/init.lua
|
@ -1341,4 +1341,51 @@ function Promise.retry(callback, times, ...)
|
||||||
end)
|
end)
|
||||||
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
|
return Promise
|
||||||
|
|
|
@ -1441,4 +1441,37 @@ return function()
|
||||||
end)
|
end)
|
||||||
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
|
end
|
Loading…
Reference in a new issue