mirror of
				https://github.com/AmberGraceRblx/luau-promise.git
				synced 2025-10-31 18:39:27 +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