]> git.lizzy.rs Git - lua_async.git/blob - promises.lua
97cd20e6ae043904ed3b0e78b753b71a57361869
[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:then_(on_resolve, on_reject)
48         local promise = Promise()
49         promise.__on_resolve = on_resolve
50         promise.__on_reject = on_reject
51
52         self:__add_child(promise)
53
54         return promise
55 end
56
57 function PromisePrototype:catch(func)
58         local promise = Promise(function() end)
59         promise.__on_reject = func
60
61         self:__add_child(promise)
62
63         return promise
64 end
65
66 function PromisePrototype:resolve(...)
67         assert(self.state == "pending")
68
69         if self.__on_resolve then
70                 self:__run_handler(self.__on_resolve, ...)
71         else
72                 self:__resolve_raw(...)
73         end
74 end
75
76 function PromisePrototype:reject(reason)
77         assert(self.state == "pending")
78
79         if self.__on_reject then
80                 self:__run_handler(self.__on_reject, reason)
81         else
82                 self:__reject_raw(reason)
83         end
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