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