]> git.lizzy.rs Git - lua_async.git/blob - promises.lua
Document resume()
[lua_async.git] / promises.lua
1 local PromisePrototype = {}
2
3 function PromisePrototype:__run_handler(func, ...)
4         local values = {pcall(func, ...)}
5
6         if table.remove(values, 1) then
7                 self:__resolve_raw(unpack(values))
8         else
9                 self:__reject_raw(values[1])
10         end
11 end
12
13 function PromisePrototype:__add_child(promise)
14         if self.state == "resolved" then
15                 promise:__resolve(unpack(self.values))
16         elseif self.state == "rejected" then
17                 promise:__reject(self.reason)
18         else
19                 table.insert(self.__children, promise)
20         end
21 end
22
23 function PromisePrototype:__resolve_raw(...)
24         self.state = "resolved"
25         self.values = {...}
26         self.reason = nil
27
28         for _, child in ipairs(self.__children) do
29                 child:resolve(...)
30         end
31 end
32
33 function PromisePrototype:__reject_raw(reason)
34         self.state = "rejected"
35         self.values = nil
36         self.reason = reason
37
38         local any_child = false
39
40         for _, child in ipairs(self.__children) do
41                 child:reject(reason)
42         end
43
44         assert(any_child, "Uncaught (in promise): " .. reason)
45 end
46
47 function PromisePrototype:resolve(...)
48         assert(self.state == "pending")
49
50         if self.__on_resolve then
51                 self:__run_handler(self.__on_resolve, ...)
52         else
53                 self:__resolve_raw(...)
54         end
55 end
56
57 function PromisePrototype:reject(reason)
58         assert(self.state == "pending")
59
60         if self.__on_reject then
61                 self:__run_handler(self.__on_reject, reason)
62         else
63                 self:__reject_raw(reason)
64         end
65 end
66
67 function PromisePrototype:then_(on_resolve, on_reject)
68         local promise = Promise()
69         promise.__on_resolve = on_resolve
70         promise.__on_reject = on_reject
71
72         self:__add_child(promise)
73
74         return promise
75 end
76
77 function PromisePrototype:catch(func)
78         local promise = Promise(function() end)
79         promise.__on_reject = func
80
81         self:__add_child(promise)
82
83         return promise
84 end
85
86 Promise = setmetatable({}, {
87         __call = function(_, resolver)
88                 local promise = {
89                         state = "pending",
90                         __children = {},
91                 }
92
93                 setmetatable(promise, {__index = PromisePrototype})
94
95                 if resolver then
96                         resolver(
97                                 function(...)
98                                         promise:resolve(...)
99                                 end,
100                                 function(...)
101                                         promise:reject(...)
102                                 end
103                         )
104                 end
105
106                 return promise
107         end
108 })
109
110 function Promise.resolve(...)
111         local args = {...}
112         return Promise(function(resolve)
113                 resolve(unpack(args))
114         end)
115 end