Skip to content

Instantly share code, notes, and snippets.

@Novaras
Created January 29, 2023 20:28
Show Gist options
  • Save Novaras/2b11f85fbfe5848d025ec352628bc51b to your computer and use it in GitHub Desktop.
Save Novaras/2b11f85fbfe5848d025ec352628bc51b to your computer and use it in GitHub Desktop.
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