Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local PromiseState = {
- pending = "pending",
- fulfilled = "fulfilled",
- rejected = "rejected"
- }
- local Promise
- local PROMISE = {}
- PROMISE.__index = PROMISE
- function PROMISE:__tostring()
- if self._state == PromiseState.pending then
- return "Promise (pending)"
- elseif self._state == PromiseState.fulfilled then
- return ("Promise (fulfilled, value=%s)"):format(tostring(self._value))
- elseif self._state == PromiseState.rejected then
- return ("Promise (rejected, reason=%s)"):format(tostring(self._reason))
- end
- end
- local function TriggerPromiseReactions(reactions, argument)
- for _, reaction in ipairs(reactions) do
- local status, val = pcall(reaction.handler, argument)
- if status then
- reaction.capabilities.resolve(val)
- else
- reaction.capabilities.reject(val)
- end
- end
- end
- function PROMISE:then_(on_fulfilled, on_rejected)
- local new_promise_resolve, new_promise_reject
- local new_promise = Promise(function(res, rej)
- new_promise_resolve, new_promise_reject = res, rej
- end)
- local result_capability = {
- promise = new_promise,
- resolve = new_promise_resolve,
- reject = new_promise_reject
- }
- on_fulfilled = on_fulfilled or function(x) return x end
- on_rejected = on_rejected or function(x) error(x) end
- local fulfill_reaction = {
- capabilities = result_capability,
- handler = on_fulfilled
- }
- local reject_reaction = {
- capabilities = result_capability,
- handler = on_rejected
- }
- if self._state == PromiseState.pending then
- self._fulfill_reactions[#self._fulfill_reactions + 1] = fulfill_reaction
- self._reject_reactions[#self._reject_reactions + 1] = reject_reaction
- elseif self._state == PromiseState.fulfilled then
- TriggerPromiseReactions({ fulfill_reaction }, self._value)
- elseif self._state == PromiseState.rejected then
- TriggerPromiseReactions({ reject_reaction }, self._reason)
- end
- return result_capability.promise
- end
- function PROMISE:theen_(on_fulfilled, on_rejected)
- local new_promise_resolve, new_promise_reject
- local new_promise = Promise(function(res, rej)
- new_promise_resolve, new_promise_reject = res, rej
- end)
- local result_capability = {
- promise = new_promise,
- resolve = new_promise_resolve,
- reject = new_promise_reject
- }
- on_fulfilled = on_fulfilled or function(x) return x end
- on_rejected = on_rejected or function(x) error(x) end
- local fulfill_reaction = {
- capabilities = result_capability,
- handler = on_fulfilled
- }
- local reject_reaction = {
- capabilities = result_capability,
- handler = on_rejected
- }
- if self._state == PromiseState.pending then
- self._fulfill_reactions[#self._fulfill_reactions + 1] = fulfill_reaction
- self._reject_reactions[#self._reject_reactions + 1] = reject_reaction
- elseif self._state == PromiseState.fulfilled then
- TriggerPromiseReactions({ fulfill_reaction }, self._value)
- elseif self._state == PromiseState.rejected then
- TriggerPromiseReactions({ reject_reaction }, self._reason)
- end
- return result_capability.promise
- end
- function PROMISE:catch(on_rejected)
- self:then_(nil, on_rejected)
- end
- function PROMISE:_fulfill(val)
- if self._state ~= PromiseState.pending then return end
- self._value = val
- TriggerPromiseReactions(self._fulfill_reactions, self._reason)
- self._fulfill_reactions = nil
- self._reject_reactions = nil
- self._state = PromiseState.fulfilled
- end
- function PROMISE:_reject(val)
- if self._state ~= PromiseState.pending then return end
- self._reason = val
- TriggerPromiseReactions(self._reject_reactions, self._reason)
- self._fulfill_reactions = nil
- self._reject_reactions = nil
- self._state = PromiseState.rejected
- end
- local function CreateResolvingFunctions(promise)
- local already_resolved = false
- local resolve, reject
- resolve = function(resolution)
- if already_resolved then return end
- already_resolved = true
- if resolution == promise then
- return promise:_reject("selfResolutionError")
- end
- if getmetatable(resolution) == PROMISE then
- local resolve2, reject2 = CreateResolvingFunctions(promise)
- local success, val = pcall(resolution.then_, resolution, resolve2, reject2)
- if not success then
- return reject2(val)
- end
- else
- return promise:_fulfill(resolution)
- end
- end
- reject = function(reason)
- if already_resolved then return end
- already_resolved = true
- return promise:_reject(reason)
- end
- return resolve, reject
- end
- Promise = setmetatable({}, {
- __call = function(_, executor)
- local promise = setmetatable({
- _state = PromiseState.pending,
- _fulfill_reactions = {},
- _reject_reactions = {}
- }, PROMISE)
- local resolve, reject = CreateResolvingFunctions(promise)
- local success, val = pcall(executor, resolve, reject)
- if not success then
- reject(val)
- end
- return promise
- end
- })
- function Promise.reject(reason)
- return Promise(function(resolve, reject)
- reject(reason)
- end)
- end
- function Promise.resolve(val)
- return Promise(function(resolve, reject)
- resolve(val)
- end)
- end
- function Promise.all()
- end
- function Promise.race()
- end
- return Promise
Advertisement
Add Comment
Please, Sign In to add comment