function AttributeUtils.promiseAttribute(w,n,a,g)assert(typeof(w)=="\073\110\115\116\097\110\099\101","\066\097\100 \105\110\115\116\097\110\099\101")assert(type(n)=="\115\116\114\105\110\103","\066\097\100 \097\116\116\114\105\098\117\116\101\078\097\109\101")assert(CancelToken.isCancelToken(g)or g==nil,"\066\097\100 \099\097\110\099\101\108\084\111\107\101\110")a=a or DEFAULT_PREDICATE do local g=w:GetAttribute(n)if a(g)then return Promise.resolved(g)end end local Q=Promise.new()local I=Maid.new()I:GiveTask(Q)if g then I:GiveTask(g.Cancelled:Connect(function()Q:Reject()end))end I:GiveTask((w:GetAttributeChangedSignal(n)):Connect(function()local g=w:GetAttribute(n)if a(g)then Q:Resolve(g)end end))Q:Finally(function()I:DoCleaning()end)return Q end
--[=[
	Promises attribute value fits predicate

	@param instance Instance
	@param attributeName string
	@param predicate function | nil
	@param cancelToken CancelToken
	@return Promise<any>
]=]
function AttributeUtils.promiseAttribute(instance, attributeName, predicate, cancelToken)
	assert(typeof(instance) == "Instance", "Bad instance")
	assert(type(attributeName) == "string", "Bad attributeName")
	assert(CancelToken.isCancelToken(cancelToken) or cancelToken == nil, "Bad cancelToken")

	predicate = predicate or DEFAULT_PREDICATE

	do
		local attributeValue = instance:GetAttribute(attributeName)
		if predicate(attributeValue) then
			return Promise.resolved(attributeValue)
		end
	end

	local promise = Promise.new()
	local maid = Maid.new()
	maid:GiveTask(promise)

	if cancelToken then
		maid:GiveTask(cancelToken.Cancelled:Connect(function()
			promise:Reject()
		end))
	end

	maid:GiveTask(instance:GetAttributeChangedSignal(attributeName):Connect(function()
		local attributeValue = instance:GetAttribute(attributeName)
		if predicate(attributeValue) then
			promise:Resolve(attributeValue)
		end
	end))

	promise:Finally(function()
		maid:DoCleaning()
	end)

	return promise
end
