evaera / roblox-lua-promise

Promise implementation for Roblox
https://eryn.io/roblox-lua-promise/
MIT License
281 stars 78 forks source link

Promise:finally counts as a consumer, but it probably shouldn't #66

Closed evaera closed 2 years ago

evaera commented 3 years ago

Somewhat related to #59. Right now, finally acts as a consumer of the root promise. This means if another consumer of the root promise (that is, a sibling of the finally promise) is cancelled, the root itself will not be cancelled because it still has a second consumer (the finally promise itself).

If we make it so that finally forwards rejection values and doesn't reset the state (#59), then we should probably also make it so that finally does not count as a proper consumer. This way attaching a finally to a chain is more or less transparent and doesn't affect the logistics of cancellation.

An example where this causes problems:

local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore"))
local Promise = require("Promise")

local function wrapPromise(x)
    return Promise.resolve(x)
end

local test = function()
    -- 'a' always has the state 'Started'.
    local a = Promise.delay(2)

    a:finally(function()
        print("Test - this should be called on cancel.")
    end)

    return a
end

local prom = test()

wait()
prom:cancel() -- This will print 'test' to the console immediately.

local prom2 = wrapPromise(test())

wait()
prom2:cancel() -- This will print 'test' to the console after **2 seconds**, as the promise can't be cancelled.