Created
January 29, 2023 20:28
-
-
Save Novaras/2b11f85fbfe5848d025ec352628bc51b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PROMISE_INDEX = PROMISE_INDEX or 0; | |
PROMISE_POLL_INTERVAL = PROMISE_POLL_INTERVAL or 0.5; | |
PROMISE_NOOP = PROMISE_NOOP or function(_) end | |
PROMISE_STATUS = PROMISE_STATUS or { | |
pending = "pending", | |
ok = "ok", | |
fail = "fail" | |
}; | |
---@alias PromiseStatus 'pending'|'ok'|'fail' | |
---@class Resolve | |
---@field _res_value? any | |
---@field _rej_value? any | |
---@field resolve fun(self: Resolve, value: any) | |
---@field reject fun(self: Resolve, value: any) | |
---@param promise_id integer | |
---@return Resolve | |
newResolve = newResolve or function(promise_id) | |
local resolve = { | |
_promise_id = promise_id, | |
_res_value = nil, | |
_rej_value = nil, | |
}; | |
function resolve:resolve(value) | |
self._res_value = value; | |
end | |
function resolve:reject(value) | |
self._rej_value = value; | |
end | |
return resolve; | |
end | |
---@alias PromiseResolveSetter fun(self: Promise, fail_callback: fun(result: any)): Promise | |
---@alias PromiseResolveCallback fun(value: any) | |
---@class Promise | |
---@field ok PromiseResolveSetter | |
---@field fail PromiseResolveSetter | |
---@field status fun(self: Promise): PromiseStatus | |
---@field value fun(self: Promise): any|nil | |
---@param callback fun(ok: PromiseResolveCallback, fail: PromiseResolveCallback) | |
---@param poll_interval? number | |
---@return Promise | |
function newPromise(callback, poll_interval) | |
local id = PROMISE_INDEX; | |
PROMISE_INDEX = PROMISE_INDEX + 1; | |
local poll_interval = poll_interval or PROMISE_POLL_INTERVAL; | |
---@type Promise | |
local promise = { | |
_id = id, | |
_resolve = newResolve(id), | |
_ok_callback = PROMISE_NOOP, | |
_fail_callback = PROMISE_NOOP, | |
_status = PROMISE_STATUS.pending, | |
}; | |
function promise:ok(ok_callback) | |
self._ok_callback = ok_callback; | |
return self; | |
end | |
function promise:fail(fail_callback) | |
self._fail_callback = fail_callback; | |
return self; | |
end | |
---@return PromiseStatus | |
function promise:status() | |
return self._status; | |
end | |
---@return any|nil | |
function promise:value() | |
return self._resolve._res_value or self._resolve._rej_value; | |
end | |
callback( | |
function (res_val) | |
%promise._resolve:resolve(res_val); | |
end, | |
function (rej_val) | |
%promise._resolve:reject(rej_val); | |
end | |
); | |
local rule_name = "_promise_" .. promise._id .. "_poll_rule"; | |
local poll = function () | |
-- print("poll for " .. %promise._id); | |
modkit.table.printTbl(%promise._resolve, "resolve"); | |
local resolve = %promise._resolve; | |
if (resolve._res_value or resolve._rej_value) then | |
Rule_Remove(%rule_name); | |
end | |
if (resolve._res_value) then | |
%promise._status = PROMISE_STATUS.ok; | |
%promise._ok_callback(resolve._res_value); | |
elseif (resolve._rej_value) then | |
%promise._status = PROMISE_STATUS.fail; | |
%promise._fail_callback(resolve._rej_value); | |
end | |
end | |
rawset(globals(), rule_name, poll); | |
Rule_AddInterval(rule_name, poll_interval); | |
return promise; | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment