Add onUnhandledRejection

Closes #54
This commit is contained in:
eryn L. K 2021-12-27 22:06:42 -05:00
parent 4e04458816
commit 9e51c039f7
2 changed files with 60 additions and 0 deletions

View file

@ -222,6 +222,7 @@ local Promise = {
Status = makeEnum("Promise.Status", { "Started", "Resolved", "Rejected", "Cancelled" }),
_getTime = os.clock,
_timeEvent = game:GetService("RunService").Heartbeat,
_unhandledRejectionCallbacks = {},
}
Promise.prototype = {}
Promise.__index = Promise.prototype
@ -1809,6 +1810,10 @@ function Promise.prototype:_reject(...)
-- Build a reasonable message
local message = string.format("Unhandled Promise rejection:\n\n%s\n\n%s", err, self._source)
for _, callback in ipairs(Promise._unhandledRejectionCallbacks) do
task.spawn(callback, self, unpack(self._values, 1, self._valuesLength))
end
if Promise.TEST then
-- Don't spam output when we're running tests.
return
@ -1986,4 +1991,25 @@ function Promise.fromEvent(event, predicate)
end)
end
--[=[
Registers a callback that runs when an unhandled rejection happens. An unhandled rejection happens when a Promise
is rejected, and the rejection is not observed with `:catch`.
The callback is called with the actual promise that rejected, followed by the rejection values.
@param callback (promise: Promise, ...: any) -- A callback that runs when an unhandled rejection happens.
@return () -> () -- Function that unregisters the `callback` when called
]=]
function Promise.onUnhandledRejection(callback)
table.insert(Promise._unhandledRejectionCallbacks, callback)
return function()
local index = table.find(Promise._unhandledRejectionCallbacks, callback)
if index then
table.remove(Promise._unhandledRejectionCallbacks, index)
end
end
end
return Promise

View file

@ -35,6 +35,40 @@ return function()
end)
end)
describe("Unhandled rejection signal", function()
it("should call unhandled rejection callbacks", function()
local badPromise = Promise.new(function(_resolve, reject)
reject(1, 2)
end)
local callCount = 0
local function callback(promise, rejectionA, rejectionB)
callCount += 1
expect(promise).to.equal(badPromise)
expect(rejectionA).to.equal(1)
expect(rejectionB).to.equal(2)
end
local unregister = Promise.onUnhandledRejection(callback)
advanceTime()
expect(callCount).to.equal(1)
unregister()
Promise.new(function(_resolve, reject)
reject(3, 4)
end)
advanceTime()
expect(callCount).to.equal(1)
end)
end)
describe("Promise.new", function()
it("should instantiate with a callback", function()
local promise = Promise.new(function() end)