Software /
code /
prosody
Annotate
util/promise.lua @ 12292:7fe5cd8a10e2
prosodyctl: Restore 'list --outdated'
Parsing --flags puts it into 'opts', so --outdated wasn't passed to
luarocks, breaking that functionality
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 17 Feb 2022 01:39:35 +0100 |
parent | 11947:073e53b72792 |
child | 12589:39ae08180c81 |
rev | line source |
---|---|
9456
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 |
9562
acf74ad0b795
Many things: switch from hacky multi-arg xpcall implementations to a standard util.xpcall
Matthew Wild <mwild1@gmail.com>
parents:
9559
diff
changeset
|
4 local xpcall = require "util.xpcall".xpcall; |
11484
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11483
diff
changeset
|
5 local unpack = table.unpack or unpack; --luacheck: ignore 113 |
9562
acf74ad0b795
Many things: switch from hacky multi-arg xpcall implementations to a standard util.xpcall
Matthew Wild <mwild1@gmail.com>
parents:
9559
diff
changeset
|
6 |
9515
2571c65b972f
util.promise: Add a string representation
Kim Alvefur <zash@zash.se>
parents:
9514
diff
changeset
|
7 function promise_mt:__tostring() |
2571c65b972f
util.promise: Add a string representation
Kim Alvefur <zash@zash.se>
parents:
9514
diff
changeset
|
8 return "promise (" .. (self._state or "invalid") .. ")"; |
2571c65b972f
util.promise: Add a string representation
Kim Alvefur <zash@zash.se>
parents:
9514
diff
changeset
|
9 end |
2571c65b972f
util.promise: Add a string representation
Kim Alvefur <zash@zash.se>
parents:
9514
diff
changeset
|
10 |
9456
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 |
9549
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:
9548
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:
9548
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:
9548
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:
9548
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:
9548
diff
changeset
|
20 return function (param) |
9559
7c65e3f38e6e
util.promise: Switch from pcall to xpcall to get tracebacks on exceptions
Matthew Wild <mwild1@gmail.com>
parents:
9558
diff
changeset
|
21 local ok, ret = xpcall(f, debug.traceback, param); |
9549
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:
9548
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:
9548
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:
9548
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:
9548
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:
9548
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:
9548
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:
9548
diff
changeset
|
28 end; |
9456
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 |
9549
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:
9548
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:
9548
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:
9548
diff
changeset
|
33 table.insert(self._pending_on_rejected, wrap_handler(on_rejected, resolve, reject, reject)); |
9456
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 |
9549
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:
9548
diff
changeset
|
36 local function next_fulfilled(promise, on_fulfilled, on_rejected, resolve, reject) -- luacheck: ignore 212/on_rejected |
9550
98de4c2e2627
util.promise: Fix missing parameters
Matthew Wild <mwild1@gmail.com>
parents:
9549
diff
changeset
|
37 wrap_handler(on_fulfilled, resolve, reject, resolve)(promise.value); |
9549
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:
9548
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:
9548
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:
9548
diff
changeset
|
40 local function next_rejected(promise, on_fulfilled, on_rejected, resolve, reject) -- luacheck: ignore 212/on_fulfilled |
9550
98de4c2e2627
util.promise: Fix missing parameters
Matthew Wild <mwild1@gmail.com>
parents:
9549
diff
changeset
|
41 wrap_handler(on_rejected, resolve, reject, reject)(promise.reason); |
9456
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 |
9745
0dbb285f903e
util.promise: Remove references to callbacks after settling promise
Kim Alvefur <zash@zash.se>
parents:
9562
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:
9562
diff
changeset
|
54 promise._pending_on_fulfilled = nil; |
0dbb285f903e
util.promise: Remove references to callbacks after settling promise
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
55 promise._pending_on_rejected = nil; |
9456
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 resolved = false; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
61 local function _resolve(v) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
62 if resolved then return; end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
63 resolved = true; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
64 if is_promise(v) then |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
65 v:next(new_resolve_functions(p)); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
66 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
|
67 p.value = v; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
68 end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
69 |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
70 end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
71 local function _reject(e) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
72 if resolved then return; end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
73 resolved = true; |
9558
5fa73fbb047f
util.promise: Remove the non-standard ability to pass a promise to reject()
Matthew Wild <mwild1@gmail.com>
parents:
9550
diff
changeset
|
74 if promise_settle(p, "rejected", next_rejected, p._pending_on_rejected, e) then |
9456
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
75 p.reason = e; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
76 end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
77 end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
78 return _resolve, _reject; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
79 end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
80 |
11947
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
81 local next_tick = function (f) |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
82 f(); |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
83 end |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
84 |
9513
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
85 local function new(f) |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
86 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:
9512
diff
changeset
|
87 if f then |
11947
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
88 next_tick(function() |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
89 local resolve, reject = new_resolve_functions(p); |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
90 local ok, ret = xpcall(f, debug.traceback, resolve, reject); |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
91 if not ok and p._state == "pending" then |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
92 reject(ret); |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
93 end |
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
94 end); |
9513
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
95 end |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
96 return p; |
9456
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
97 end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
98 |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
99 local function all(promises) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
100 return new(function (resolve, reject) |
11483
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
101 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:
11211
diff
changeset
|
102 local total = 0; |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
103 for k, v in pairs(promises) do |
11485
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
104 if is_promise(v) then |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
105 total = total + 1; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
106 v:next(function (value) |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
107 results[k] = value; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
108 settled = settled + 1; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
109 if settled == total and loop_finished then |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
110 resolve(results); |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
111 end |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
112 end, reject); |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
113 else |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
114 results[k] = v; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
115 end |
9456
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
116 end |
11483
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
117 loop_finished = true; |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
118 if settled == total then |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
119 resolve(results); |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
120 end |
9456
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
121 end); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
122 end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
123 |
10922
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9745
diff
changeset
|
124 local function all_settled(promises) |
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9745
diff
changeset
|
125 return new(function (resolve) |
11483
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
126 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:
11211
diff
changeset
|
127 local total = 0; |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
128 for k, v in pairs(promises) do |
11485
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
129 if is_promise(v) then |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
130 total = total + 1; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
131 v:next(function (value) |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
132 results[k] = { status = "fulfilled", value = value }; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
133 settled = settled + 1; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
134 if settled == total and loop_finished then |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
135 resolve(results); |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
136 end |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
137 end, function (e) |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
138 results[k] = { status = "rejected", reason = e }; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
139 settled = settled + 1; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
140 if settled == total and loop_finished then |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
141 resolve(results); |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
142 end |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
143 end); |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
144 else |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
145 results[k] = v; |
7d42ed3a8a40
util.promise: all()/all_settled() pass through non-promise values
Matthew Wild <mwild1@gmail.com>
parents:
11484
diff
changeset
|
146 end |
10922
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9745
diff
changeset
|
147 end |
11483
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
148 loop_finished = true; |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
149 if settled == total then |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
150 resolve(results); |
24ce9d380475
util.promise: Add support for arbitrary keys in all()/all_settled()
Matthew Wild <mwild1@gmail.com>
parents:
11211
diff
changeset
|
151 end |
10922
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9745
diff
changeset
|
152 end); |
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9745
diff
changeset
|
153 end |
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9745
diff
changeset
|
154 |
11486
78d843faaffc
util.promise: Switch order of parameters to join()
Matthew Wild <mwild1@gmail.com>
parents:
11485
diff
changeset
|
155 local function join(handler, ...) |
11484
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11483
diff
changeset
|
156 local promises, n = { ... }, select("#", ...); |
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11483
diff
changeset
|
157 return all(promises):next(function (results) |
11486
78d843faaffc
util.promise: Switch order of parameters to join()
Matthew Wild <mwild1@gmail.com>
parents:
11485
diff
changeset
|
158 return handler(unpack(results, 1, n)); |
11484
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11483
diff
changeset
|
159 end); |
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11483
diff
changeset
|
160 end |
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11483
diff
changeset
|
161 |
9456
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
162 local function race(promises) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
163 return new(function (resolve, reject) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
164 for i = 1, #promises do |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
165 promises[i]:next(resolve, reject); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
166 end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
167 end); |
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 |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
170 local function resolve(v) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
171 return new(function (_resolve) |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
172 _resolve(v); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
173 end); |
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 |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
176 local function reject(v) |
9510
8ef46d09386a
util.promise: Fix promise.reject() to return a rejected promise, and fix buggy test for it
Matthew Wild <mwild1@gmail.com>
parents:
9456
diff
changeset
|
177 return new(function (_, _reject) |
9456
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
178 _reject(v); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
179 end); |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
180 end |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
181 |
9517
b1c6ede17592
util.promise: Add promise.try()
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
182 local function try(f) |
b1c6ede17592
util.promise: Add promise.try()
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
183 return resolve():next(function () return f(); end); |
b1c6ede17592
util.promise: Add promise.try()
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
184 end |
b1c6ede17592
util.promise: Add promise.try()
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
185 |
9513
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
186 function promise_methods:next(on_fulfilled, on_rejected) |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
187 return new(function (resolve, reject) --luacheck: ignore 431/resolve 431/reject |
9549
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:
9548
diff
changeset
|
188 self:_next(on_fulfilled, on_rejected, resolve, reject); |
9513
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
189 end); |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
190 end |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
191 |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
192 function promise_methods:catch(on_rejected) |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
193 return self:next(nil, on_rejected); |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
194 end |
4f4f9823bd1d
util.promise: Some code relocation
Matthew Wild <mwild1@gmail.com>
parents:
9512
diff
changeset
|
195 |
9514
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9513
diff
changeset
|
196 function promise_methods:finally(on_finally) |
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9513
diff
changeset
|
197 local function _on_finally(value) on_finally(); return value; end |
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9513
diff
changeset
|
198 local function _on_catch_finally(err) on_finally(); return reject(err); end |
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9513
diff
changeset
|
199 return self:next(_on_finally, _on_catch_finally); |
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9513
diff
changeset
|
200 end |
9db707a86a25
util.promise: Add promise:finally()
Matthew Wild <mwild1@gmail.com>
parents:
9513
diff
changeset
|
201 |
9456
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
202 return { |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
203 new = new; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
204 resolve = resolve; |
11484
a0120e935442
util.promise: Add join() convenience method
Matthew Wild <mwild1@gmail.com>
parents:
11483
diff
changeset
|
205 join = join; |
9456
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
206 reject = reject; |
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
207 all = all; |
10922
7d3dbb9eb3eb
util.promise: Add all_settled, which follows semantics of allSettled from ES2020
Matthew Wild <mwild1@gmail.com>
parents:
9745
diff
changeset
|
208 all_settled = all_settled; |
9456
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
209 race = race; |
9517
b1c6ede17592
util.promise: Add promise.try()
Matthew Wild <mwild1@gmail.com>
parents:
9515
diff
changeset
|
210 try = try; |
9548
a83afc22e9d7
util.promise: Export is_promise()
Matthew Wild <mwild1@gmail.com>
parents:
9546
diff
changeset
|
211 is_promise = is_promise; |
11947
073e53b72792
util.promise: Support delayed promise execution
Kim Alvefur <zash@zash.se>
parents:
11486
diff
changeset
|
212 set_nexttick = function(new_next_tick) next_tick = new_next_tick; end; |
9456
d54a0e129af8
util.promise: ES6-like API for promises
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
213 } |