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> |       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