]> git.lizzy.rs Git - lua_async.git/blob - promises.lua
Merge branch 'master' of https://github.com/EliasFleckenstein03/lua_async
[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                 any_child = true
43                 child:reject(reason)
44         end
45
46         assert(any_child, "Uncaught (in promise): " .. reason)
47 end
48
49 function PromisePrototype:then_(on_resolve, on_reject)
50         local promise = Promise()
51         promise.__on_resolve = on_resolve
52         promise.__on_reject = on_reject
53
54         self:__add_child(promise)
55
56         return promise
57 end
58
59 function PromisePrototype:catch(func)
60         local promise = Promise(function() end)
61         promise.__on_reject = func
62
63         self:__add_child(promise)
64
65         return promise
66 end
67
68 function PromisePrototype:resolve(...)
69         assert(self.state == "pending")
70
71         if self.__on_resolve then
72                 self:__run_handler(self.__on_resolve, ...)
73         else
74                 self:__resolve_raw(...)
75         end
76 end
77
78 function PromisePrototype:reject(reason)
79         assert(self.state == "pending")
80
81         if self.__on_reject then
82                 self:__run_handler(self.__on_reject, reason)
83         else
84                 self:__reject_raw(reason)
85         end
86 end
87
88 Promise = setmetatable({}, {
89         __call = function(_, resolver)
90                 local promise = setmetatable({
91                         state = "pending",
92                         __children = {},
93                 }, {__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