You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
2.5 KiB
Lua

local M = {}
local luv = vim.loop
function M.promisify(fn)
return function(...)
local args = { ... }
return M.new(function(resolve, reject)
table.insert(args, function(err, v)
if err then
return reject(err)
end
resolve(v)
end)
fn(unpack(args))
end)
end
end
local function set_timeout(timeout, fn)
local timer = luv.new_timer()
timer:start(timeout, 0, function()
timer:stop()
timer:close()
fn()
end)
return timer
end
function M.new(sink)
local p = setmetatable({
result = nil,
is_resolved = false,
is_errored = false,
cbs = {},
err_cbs = {},
}, {
__index = M,
})
p._resolve = function(v)
p:_set_result(v, false)
end
p._reject = function(err)
p:_set_result(err, true)
end
local success, err = pcall(function()
sink(p._resolve, p._reject)
end)
if not success then
p._reject(err)
end
return p
end
function M:then_(on_success, on_error)
local p = self
return M.new(function(resolve, reject)
table.insert(p.cbs, function(result)
if not on_success then
return resolve(result)
end
local success, res = pcall(function()
resolve(on_success(result))
end)
if not success then
reject(res)
end
return res
end)
table.insert(p.err_cbs, function(result)
if not on_error then
return reject(result)
end
local success, res = pcall(function()
resolve(on_error(result))
end)
if not success then
reject(res)
end
return res
end)
p:_exec_handlers()
end)
end
function M:catch(on_error)
return self:then_(nil, on_error)
end
function M:_exec_handlers()
if self.is_resolved then
for _, cb in ipairs(self.cbs) do
cb(self.result)
end
self.cbs = {}
self.err_cbs = {}
elseif self.is_errored then
for _, cb in ipairs(self.err_cbs) do
cb(self.result)
end
self.cbs = {}
self.err_cbs = {}
end
end
function M:_set_result(result, errored)
local p = self
set_timeout(0, function()
if p.is_resolved or p.is_errored then
return
end
if M.is_promise(result) then
return result:then_(p._resolve, p._reject)
end
p.result = result
if errored then
p.is_errored = true
else
p.is_resolved = true
end
p:_exec_handlers()
end)
end
function M.is_promise(v)
return type(v) == "table" and type(v.then_) == "function"
end
return M