mirror of
https://github.com/bjc/prosody.git
synced 2025-04-03 21:27:38 +03:00
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
This commit is contained in:
parent
c7d9ee0bb8
commit
b74a643e34
2 changed files with 60 additions and 22 deletions
|
@ -138,6 +138,43 @@ describe("util.promise", function ()
|
|||
assert.equal("ok", result);
|
||||
end);
|
||||
|
||||
it("propagates errors down the chain, even when some handlers are not provided", function ()
|
||||
local r, result;
|
||||
local test_error = {};
|
||||
local p = promise.new(function (resolve, reject)
|
||||
r = resolve;
|
||||
end);
|
||||
local cb = spy.new(function () end);
|
||||
local err_cb = spy.new(function (e) result = e end);
|
||||
local p2 = p:next(function () error(test_error) end);
|
||||
local p3 = p2:next(cb)
|
||||
p3:catch(err_cb);
|
||||
assert.spy(cb).was_called(0);
|
||||
assert.spy(err_cb).was_called(0);
|
||||
r("oh doh");
|
||||
assert.spy(cb).was_called(0);
|
||||
assert.spy(err_cb).was_called(1);
|
||||
assert.equal(test_error, result);
|
||||
end);
|
||||
|
||||
it("propagates values down the chain, even when some handlers are not provided", function ()
|
||||
local r;
|
||||
local p = promise.new(function (resolve, reject)
|
||||
r = resolve;
|
||||
end);
|
||||
local cb = spy.new(function () end);
|
||||
local err_cb = spy.new(function () end);
|
||||
local p2 = p:next(function (v) return v; end);
|
||||
local p3 = p2:catch(err_cb)
|
||||
p3:next(cb);
|
||||
assert.spy(cb).was_called(0);
|
||||
assert.spy(err_cb).was_called(0);
|
||||
r(1337);
|
||||
assert.spy(cb).was_called(1);
|
||||
assert.spy(cb).was_called_with(1337);
|
||||
assert.spy(err_cb).was_called(0);
|
||||
end);
|
||||
|
||||
describe("race()", function ()
|
||||
it("works with fulfilled promises", function ()
|
||||
local p1, p2 = promise.resolve("yep"), promise.resolve("nope");
|
||||
|
|
|
@ -10,17 +10,32 @@ local function is_promise(o)
|
|||
return mt == promise_mt;
|
||||
end
|
||||
|
||||
local function next_pending(self, on_fulfilled, on_rejected)
|
||||
table.insert(self._pending_on_fulfilled, on_fulfilled);
|
||||
table.insert(self._pending_on_rejected, on_rejected);
|
||||
local function wrap_handler(f, resolve, reject, default)
|
||||
if not f then
|
||||
return default;
|
||||
end
|
||||
return function (param)
|
||||
local ok, ret = pcall(f, param);
|
||||
if ok then
|
||||
resolve(ret);
|
||||
else
|
||||
reject(ret);
|
||||
end
|
||||
return true;
|
||||
end;
|
||||
end
|
||||
|
||||
local function next_fulfilled(promise, on_fulfilled, on_rejected) -- luacheck: ignore 212/on_rejected
|
||||
on_fulfilled(promise.value);
|
||||
local function next_pending(self, on_fulfilled, on_rejected, resolve, reject)
|
||||
table.insert(self._pending_on_fulfilled, wrap_handler(on_fulfilled, resolve, reject, resolve));
|
||||
table.insert(self._pending_on_rejected, wrap_handler(on_rejected, resolve, reject, reject));
|
||||
end
|
||||
|
||||
local function next_rejected(promise, on_fulfilled, on_rejected) -- luacheck: ignore 212/on_fulfilled
|
||||
on_rejected(promise.reason);
|
||||
local function next_fulfilled(promise, on_fulfilled, on_rejected, resolve, reject) -- luacheck: ignore 212/on_rejected
|
||||
wrap_handler(on_fulfilled, resolve, reject)(promise.value);
|
||||
end
|
||||
|
||||
local function next_rejected(promise, on_fulfilled, on_rejected, resolve, reject) -- luacheck: ignore 212/on_fulfilled
|
||||
wrap_handler(on_rejected, resolve, reject)(promise.reason);
|
||||
end
|
||||
|
||||
local function promise_settle(promise, new_state, new_next, cbs, value)
|
||||
|
@ -59,17 +74,6 @@ local function new_resolve_functions(p)
|
|||
return _resolve, _reject;
|
||||
end
|
||||
|
||||
local function wrap_handler(f, resolve, reject)
|
||||
return function (param)
|
||||
local ok, ret = pcall(f, param);
|
||||
if ok then
|
||||
resolve(ret);
|
||||
else
|
||||
reject(ret);
|
||||
end
|
||||
end;
|
||||
end
|
||||
|
||||
local function new(f)
|
||||
local p = setmetatable({ _state = "pending", _next = next_pending, _pending_on_fulfilled = {}, _pending_on_rejected = {} }, promise_mt);
|
||||
if f then
|
||||
|
@ -123,10 +127,7 @@ end
|
|||
|
||||
function promise_methods:next(on_fulfilled, on_rejected)
|
||||
return new(function (resolve, reject) --luacheck: ignore 431/resolve 431/reject
|
||||
self:_next(
|
||||
on_fulfilled and wrap_handler(on_fulfilled, resolve, reject) or nil,
|
||||
on_rejected and wrap_handler(on_rejected, resolve, reject) or nil
|
||||
);
|
||||
self:_next(on_fulfilled, on_rejected, resolve, reject);
|
||||
end);
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue