Comparison

util/promise.lua @ 9549:800c274928bf

util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
author Matthew Wild <mwild1@gmail.com>
date Thu, 25 Oct 2018 14:38:00 +0100
parent 9548:a83afc22e9d7
child 9550:98de4c2e2627
comparison
equal deleted inserted replaced
9548:a83afc22e9d7 9549:800c274928bf
8 local function is_promise(o) 8 local function is_promise(o)
9 local mt = getmetatable(o); 9 local mt = getmetatable(o);
10 return mt == promise_mt; 10 return mt == promise_mt;
11 end 11 end
12 12
13 local function next_pending(self, on_fulfilled, on_rejected) 13 local function wrap_handler(f, resolve, reject, default)
14 table.insert(self._pending_on_fulfilled, on_fulfilled); 14 if not f then
15 table.insert(self._pending_on_rejected, on_rejected); 15 return default;
16 end
17 return function (param)
18 local ok, ret = pcall(f, param);
19 if ok then
20 resolve(ret);
21 else
22 reject(ret);
23 end
24 return true;
25 end;
16 end 26 end
17 27
18 local function next_fulfilled(promise, on_fulfilled, on_rejected) -- luacheck: ignore 212/on_rejected 28 local function next_pending(self, on_fulfilled, on_rejected, resolve, reject)
19 on_fulfilled(promise.value); 29 table.insert(self._pending_on_fulfilled, wrap_handler(on_fulfilled, resolve, reject, resolve));
30 table.insert(self._pending_on_rejected, wrap_handler(on_rejected, resolve, reject, reject));
20 end 31 end
21 32
22 local function next_rejected(promise, on_fulfilled, on_rejected) -- luacheck: ignore 212/on_fulfilled 33 local function next_fulfilled(promise, on_fulfilled, on_rejected, resolve, reject) -- luacheck: ignore 212/on_rejected
23 on_rejected(promise.reason); 34 wrap_handler(on_fulfilled, resolve, reject)(promise.value);
35 end
36
37 local function next_rejected(promise, on_fulfilled, on_rejected, resolve, reject) -- luacheck: ignore 212/on_fulfilled
38 wrap_handler(on_rejected, resolve, reject)(promise.reason);
24 end 39 end
25 40
26 local function promise_settle(promise, new_state, new_next, cbs, value) 41 local function promise_settle(promise, new_state, new_next, cbs, value)
27 if promise._state ~= "pending" then 42 if promise._state ~= "pending" then
28 return; 43 return;
55 elseif promise_settle(p, "rejected", next_rejected, p._pending_on_rejected, e) then 70 elseif promise_settle(p, "rejected", next_rejected, p._pending_on_rejected, e) then
56 p.reason = e; 71 p.reason = e;
57 end 72 end
58 end 73 end
59 return _resolve, _reject; 74 return _resolve, _reject;
60 end
61
62 local function wrap_handler(f, resolve, reject)
63 return function (param)
64 local ok, ret = pcall(f, param);
65 if ok then
66 resolve(ret);
67 else
68 reject(ret);
69 end
70 end;
71 end 75 end
72 76
73 local function new(f) 77 local function new(f)
74 local p = setmetatable({ _state = "pending", _next = next_pending, _pending_on_fulfilled = {}, _pending_on_rejected = {} }, promise_mt); 78 local p = setmetatable({ _state = "pending", _next = next_pending, _pending_on_fulfilled = {}, _pending_on_rejected = {} }, promise_mt);
75 if f then 79 if f then
121 return resolve():next(function () return f(); end); 125 return resolve():next(function () return f(); end);
122 end 126 end
123 127
124 function promise_methods:next(on_fulfilled, on_rejected) 128 function promise_methods:next(on_fulfilled, on_rejected)
125 return new(function (resolve, reject) --luacheck: ignore 431/resolve 431/reject 129 return new(function (resolve, reject) --luacheck: ignore 431/resolve 431/reject
126 self:_next( 130 self:_next(on_fulfilled, on_rejected, resolve, reject);
127 on_fulfilled and wrap_handler(on_fulfilled, resolve, reject) or nil,
128 on_rejected and wrap_handler(on_rejected, resolve, reject) or nil
129 );
130 end); 131 end);
131 end 132 end
132 133
133 function promise_methods:catch(on_rejected) 134 function promise_methods:catch(on_rejected)
134 return self:next(nil, on_rejected); 135 return self:next(nil, on_rejected);