author | Kim Alvefur <zash@zash.se> |
Sat, 02 Mar 2024 14:08:47 +0100 | |
changeset 13458 | b0c27628f588 |
parent 12979 | d10957394a3c |
permissions | -rw-r--r-- |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1 |
local promise_methods = {}; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
2 |
local promise_mt = { __name = "promise", __index = promise_methods }; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
3 |
|
12979
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12754
diff
changeset
|
4 |
local xpcall = require "prosody.util.xpcall".xpcall; |
12593
39ae08180c81
compat: Remove handling of Lua 5.1 location of 'unpack' function
Kim Alvefur <zash@zash.se>
parents:
11951
diff
changeset
|
5 |
local unpack = table.unpack; |
9565
acf74ad0b795
Many things: switch from hacky multi-arg xpcall implementations to a standard util.xpcall
Matthew Wild <mwild1@gmail.com>
parents:
9562
diff
changeset
|
6 |
|
9518
2571c65b972f
util.promise: Add a string representation
Kim Alvefur <zash@zash.se>
parents:
9517
diff
changeset
|
7 |
function promise_mt:__tostring() |
2571c65b972f
util.promise: Add a string representation
Kim Alvefur <zash@zash.se>
parents:
9517
diff
changeset
|
8 |
return "promise (" .. (self._state or "invalid") .. ")"; |
2571c65b972f
util.promise: Add a string representation
Kim Alvefur <zash@zash.se>
parents:
9517
diff
changeset
|
9 |
end |
2571c65b972f
util.promise: Add a string representation
Kim Alvefur <zash@zash.se>
parents:
9517
diff
changeset
|
10 |
|
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
11 |
local function is_promise(o) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
12 |
local mt = getmetatable(o); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
13 |
return mt == promise_mt; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
14 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
15 |
|
9552
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
16 |
local function wrap_handler(f, resolve, reject, default) |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
17 |
if not f then |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
18 |
return default; |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
19 |
end |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
20 |
return function (param) |
9562
7c65e3f38e6e
util.promise: Switch from pcall to xpcall to get tracebacks on exceptions
Matthew Wild <mwild1@gmail.com>
parents:
9561
diff
changeset
|
21 |
local ok, ret = xpcall(f, debug.traceback, param); |
9552
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
22 |
if ok then |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
23 |
resolve(ret); |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
24 |
else |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
25 |
reject(ret); |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
26 |
end |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
27 |
return true; |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
28 |
end; |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
29 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
30 |
|
9552
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
31 |
local function next_pending(self, on_fulfilled, on_rejected, resolve, reject) |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
32 |
table.insert(self._pending_on_fulfilled, wrap_handler(on_fulfilled, resolve, reject, resolve)); |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
33 |
table.insert(self._pending_on_rejected, wrap_handler(on_rejected, resolve, reject, reject)); |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
34 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
35 |
|
9552
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
36 |
local function next_fulfilled(promise, on_fulfilled, on_rejected, resolve, reject) -- luacheck: ignore 212/on_rejected |
9553
98de4c2e2627
util.promise: Fix missing parameters
Matthew Wild <mwild1@gmail.com>
parents:
9552
diff
changeset
|
37 |
wrap_handler(on_fulfilled, resolve, reject, resolve)(promise.value); |
9552
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
38 |
end |
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
39 |
|
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
40 |
local function next_rejected(promise, on_fulfilled, on_rejected, resolve, reject) -- luacheck: ignore 212/on_fulfilled |
9553
98de4c2e2627
util.promise: Fix missing parameters
Matthew Wild <mwild1@gmail.com>
parents:
9552
diff
changeset
|
41 |
wrap_handler(on_rejected, resolve, reject, reject)(promise.reason); |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
42 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
43 |
|
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
44 |
local function promise_settle(promise, new_state, new_next, cbs, value) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
45 |
if promise._state ~= "pending" then |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
46 |
return; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
47 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
48 |
promise._state = new_state; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
49 |
promise._next = new_next; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
50 |
for _, cb in ipairs(cbs) do |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
51 |
cb(value); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
52 |
end |
9749
0dbb285f903e
util.promise: Remove references to callbacks after settling promise
Kim Alvefur <zash@zash.se>
parents:
9565
diff
changeset
|
53 |
-- No need to keep references to callbacks |
0dbb285f903e
util.promise: Remove references to callbacks after settling promise
Kim Alvefur <zash@zash.se>
parents:
9565
diff
changeset
|
54 |
promise._pending_on_fulfilled = nil; |
0dbb285f903e
util.promise: Remove references to callbacks after settling promise
Kim Alvefur <zash@zash.se>
parents:
9565
diff
changeset
|
55 |
promise._pending_on_rejected = nil; |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
56 |
return true; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
57 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
58 |
|
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
59 |
local function new_resolve_functions(p) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
60 |
local function _resolve(v) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
61 |
if is_promise(v) then |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
62 |
v:next(new_resolve_functions(p)); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
63 |
elseif promise_settle(p, "fulfilled", next_fulfilled, p._pending_on_fulfilled, v) then |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
64 |
p.value = v; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
65 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
66 |
|
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
67 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
68 |
local function _reject(e) |
9561
5fa73fbb047f
util.promise: Remove the non-standard ability to pass a promise to reject()
Matthew Wild <mwild1@gmail.com>
parents:
9553
diff
changeset
|
69 |
if promise_settle(p, "rejected", next_rejected, p._pending_on_rejected, e) then |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
70 |
p.reason = e; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
71 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
72 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
73 |
return _resolve, _reject; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
74 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
75 |
|
11951
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
76 |
local next_tick = function (f) |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
77 |
f(); |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
78 |
end |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
79 |
|
9516
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
80 |
local function new(f) |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
81 |
local p = setmetatable({ _state = "pending", _next = next_pending, _pending_on_fulfilled = {}, _pending_on_rejected = {} }, promise_mt); |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
82 |
if f then |
11951
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
83 |
next_tick(function() |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
84 |
local resolve, reject = new_resolve_functions(p); |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
85 |
local ok, ret = xpcall(f, debug.traceback, resolve, reject); |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
86 |
if not ok and p._state == "pending" then |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
87 |
reject(ret); |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
88 |
end |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
89 |
end); |
9516
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
90 |
end |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
91 |
return p; |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
92 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
93 |
|
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
94 |
local function all(promises) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
95 |
return new(function (resolve, reject) |
11487
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
96 |
local settled, results, loop_finished = 0, {}, false; |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
97 |
local total = 0; |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
98 |
for k, v in pairs(promises) do |
11489
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
99 |
if is_promise(v) then |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
100 |
total = total + 1; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
101 |
v:next(function (value) |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
102 |
results[k] = value; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
103 |
settled = settled + 1; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
104 |
if settled == total and loop_finished then |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
105 |
resolve(results); |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
106 |
end |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
107 |
end, reject); |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
108 |
else |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
109 |
results[k] = v; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
110 |
end |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
111 |
end |
11487
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
112 |
loop_finished = true; |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
113 |
if settled == total then |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
114 |
resolve(results); |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
115 |
end |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
116 |
end); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
117 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
118 |
|
10926
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9749
diff
changeset
|
119 |
local function all_settled(promises) |
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9749
diff
changeset
|
120 |
return new(function (resolve) |
11487
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
121 |
local settled, results, loop_finished = 0, {}, false; |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
122 |
local total = 0; |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
123 |
for k, v in pairs(promises) do |
11489
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
124 |
if is_promise(v) then |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
125 |
total = total + 1; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
126 |
v:next(function (value) |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
127 |
results[k] = { status = "fulfilled", value = value }; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
128 |
settled = settled + 1; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
129 |
if settled == total and loop_finished then |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
130 |
resolve(results); |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
131 |
end |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
132 |
end, function (e) |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
133 |
results[k] = { status = "rejected", reason = e }; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
134 |
settled = settled + 1; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
135 |
if settled == total and loop_finished then |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
136 |
resolve(results); |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
137 |
end |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
138 |
end); |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
139 |
else |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
140 |
results[k] = v; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11488
diff
changeset
|
141 |
end |
10926
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9749
diff
changeset
|
142 |
end |
11487
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
143 |
loop_finished = true; |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
144 |
if settled == total then |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
145 |
resolve(results); |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11215
diff
changeset
|
146 |
end |
10926
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9749
diff
changeset
|
147 |
end); |
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9749
diff
changeset
|
148 |
end |
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9749
diff
changeset
|
149 |
|
11490
78d843faaffc
util.promise: Switch order of parameters to join()
Matthew Wild <mwild1@gmail.com>
parents:
11489
diff
changeset
|
150 |
local function join(handler, ...) |
11488
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11487
diff
changeset
|
151 |
local promises, n = { ... }, select("#", ...); |
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11487
diff
changeset
|
152 |
return all(promises):next(function (results) |
11490
78d843faaffc
util.promise: Switch order of parameters to join()
Matthew Wild <mwild1@gmail.com>
parents:
11489
diff
changeset
|
153 |
return handler(unpack(results, 1, n)); |
11488
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11487
diff
changeset
|
154 |
end); |
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11487
diff
changeset
|
155 |
end |
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11487
diff
changeset
|
156 |
|
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
157 |
local function race(promises) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
158 |
return new(function (resolve, reject) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
159 |
for i = 1, #promises do |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
160 |
promises[i]:next(resolve, reject); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
161 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
162 |
end); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
163 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
164 |
|
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
165 |
local function resolve(v) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
166 |
return new(function (_resolve) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
167 |
_resolve(v); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
168 |
end); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
169 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
170 |
|
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
171 |
local function reject(v) |
9513
8ef46d09386a
util.promise: Fix promise.reject() to return a rejected promise, and fix buggy test for it
Matthew Wild <mwild1@gmail.com>
parents:
9459
diff
changeset
|
172 |
return new(function (_, _reject) |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
173 |
_reject(v); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
174 |
end); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
175 |
end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
176 |
|
9520
b1c6ede17592
util.promise: Add promise.try()
Matthew Wild <mwild1@gmail.com>
parents:
9518
diff
changeset
|
177 |
local function try(f) |
b1c6ede17592
util.promise: Add promise.try()
Matthew Wild <mwild1@gmail.com>
parents:
9518
diff
changeset
|
178 |
return resolve():next(function () return f(); end); |
b1c6ede17592
util.promise: Add promise.try()
Matthew Wild <mwild1@gmail.com>
parents:
9518
diff
changeset
|
179 |
end |
b1c6ede17592
util.promise: Add promise.try()
Matthew Wild <mwild1@gmail.com>
parents:
9518
diff
changeset
|
180 |
|
9516
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
181 |
function promise_methods:next(on_fulfilled, on_rejected) |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
182 |
return new(function (resolve, reject) --luacheck: ignore 431/resolve 431/reject |
9552
800c274928bf
util.promise: Ensure chained promises always receive a value/rejection even if an intermediate promise has no handlers
Matthew Wild <mwild1@gmail.com>
parents:
9551
diff
changeset
|
183 |
self:_next(on_fulfilled, on_rejected, resolve, reject); |
9516
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
184 |
end); |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
185 |
end |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
186 |
|
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
187 |
function promise_methods:catch(on_rejected) |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
188 |
return self:next(nil, on_rejected); |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
189 |
end |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
190 |
|
9517
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9516
diff
changeset
|
191 |
function promise_methods:finally(on_finally) |
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9516
diff
changeset
|
192 |
local function _on_finally(value) on_finally(); return value; end |
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9516
diff
changeset
|
193 |
local function _on_catch_finally(err) on_finally(); return reject(err); end |
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9516
diff
changeset
|
194 |
return self:next(_on_finally, _on_catch_finally); |
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9516
diff
changeset
|
195 |
end |
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9516
diff
changeset
|
196 |
|
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
197 |
return { |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
198 |
new = new; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
199 |
resolve = resolve; |
11488
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11487
diff
changeset
|
200 |
join = join; |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
201 |
reject = reject; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
202 |
all = all; |
10926
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9749
diff
changeset
|
203 |
all_settled = all_settled; |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
204 |
race = race; |
9520
b1c6ede17592
util.promise: Add promise.try()
Matthew Wild <mwild1@gmail.com>
parents:
9518
diff
changeset
|
205 |
try = try; |
9551
a83afc22e9d7
util.promise: Export is_promise()
Matthew Wild <mwild1@gmail.com>
parents:
9549
diff
changeset
|
206 |
is_promise = is_promise; |
11951
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11490
diff
changeset
|
207 |
set_nexttick = function(new_next_tick) next_tick = new_next_tick; end; |
9459
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
208 |
} |