promise library for minetest
Overview
Features:
- Async event handling
- Utilities for formspec, emerge_area, handle_async, http and minetest.after
Examples
Simple promise and handling:
-- create promise
local p = Promise.new(function(resolve, reject)
-- async operation here, mocked for this example
minetest.after(1, function()
resolve("result-from-a-long-operation")
end)
end)
-- handle the result later
p:next(function(result)
assert(result == "result-from-a-long-operation")
end)
Chained async operations:
Promise.emerge_area(pos1, pos2):next(function()
-- delay a second before next operation
return Promise.after(1)
end):next(function()
-- called after emerge + 1 second delay
end)
Wait for multiple http requests:
local http = minetest.request_http_api()
local p1 = Promise.http(http, "http://localhost/x")
local p2 = Promise.http(http, "http://localhost/y")
Promise.all(p1, p2):next(function(values)
local x = values[1]
local y = values[2]
end)
Wait for multiple async workers:
local fn = function(x,y)
return x*y
end
local p1 = Promise.handle_async(fn, 1, 1)
local p2 = Promise.handle_async(fn, 2, 2)
local p3 = Promise.handle_async(fn, 10, 2)
Promise.all(p1, p2, p3):next(function(values)
assert(values[1] == 1)
assert(values[2] == 4)
assert(values[3] == 20)
end)
Api
Promise.new(callback)
Creates a new promise
Example:
local p = Promise.new(function(resolve, reject)
-- TODO: async operation and resolve(value) or reject(err)
end)
-- test if the value is a promise
assert(p.is_promise == true)
p:then(function(result)
-- TODO: handle the result
end):catch(function(err)
-- TODO: handle the error
end)
Alternatively:
-- promise without callback
local p = Promise.new()
-- later on: resolve from outside
p:resolve(result)
Promise.resolved(value)
Returns an already resolved promise with given value
Promise.rejected(err)
Returns an already rejected promise with given error
Promise.all(...)
Wait for all promises to finish
Example:
local p1 = Promise.resolved(5)
local p2 = Promise.resolved(10)
Promise.all(p1, p2):next(function(values)
assert(#values == 2)
assert(values[1] == 5)
assert(values[2] == 10)
end)
Promise.race(...)
Wait for the first promise to finish
Example:
local p1 = Promise.resolved(5)
local p2 = Promise.new()
Promise.race(p1, p2):next(function(v)
assert(v == 5)
end)
Promise.after(delay, value, err)
Returns a delayed promise that resolves to given value or error
Promise.emerge_area(pos1, pos2)
Emerges the given area and resolves afterwards
Promise.formspec(player, formspec, callback)
Formspec shorthand / util
Example:
Promise.formspec(player, "size[2,2]button_exit[0,0;2,2;mybutton;label]")
:next(function(data)
-- formspec closed
assert(data.player:get_player_name())
assert(data.fields.mybutton == true)
end)
NOTE: the promise only resolves if the player exits the formspec (with a quit="true"
value, a default in exit_buttons)
Example with optional scroll/dropdown callbacks:
local callback = function(fields)
-- TODO: handle CHG, and other "non-quit" events here
end
Promise.formspec(player, "size[2,2]button_exit[0,0;2,2;mybutton;label]", callback)
:next(function(data)
-- formspec closed
assert(data.player:get_player_name())
assert(data.fields.mybutton == true)
end)
Promise.handle_async(fn, args...)
Executes the function fn
in the async environment with given arguments
NOTE: This falls back to a simple function-call if the minetest.handle_async
function isn't available.
Promise.http(http, url, opts)
Http query
http
The http instance returned fromminetest.request_http_api()
url
The url to callopts
Table with options:json
parse result as json (default: false)method
The http method (default: "GET")timeout
Timeout in seconds (default: 10)data
Data to transfer, serialized as json if type istable
headers
table of additional headers
Examples:
local http = minetest.request_http_api()
-- call chuck norris api: https://api.chucknorris.io/ and expect json-response
Promise.http(http, "https://api.chucknorris.io/jokes/random", { json = true })
:next(function(joke)
assert(type(joke.value) == "string")
end)
-- post json-payload with 10 second timeout and expect raw string-response (or error)
Promise.http(http, "http://localhost/stuff", { method = "POST", timeout = 10, data = { x=123 } })
:next(function(result)
assert(result)
end):catch(function(result)
-- result.code can be 0 if the timeout was reached
assert(result.code == 500)
assert(result.data == "Server error")
end)
Promise.mods_loaded()
Resolved on mods loaded (minetest.register_on_mods_loaded
)
Example:
Promise.mods_loaded():next(function()
-- stuff that runs when all mods are loaded
end)
Promise.dynamic_add_media(options)
Dynamic media push
Example:
Promise.dynamic_add_media({ filepath = "world/image.png", to_player = "singleplayer" })
:next(function(name)
-- player callback
end):catch(function()
-- error handling
end)
NOTE: experimental, only works if the to_player
property is set
License
- Code: MIT (adapted from https://github.com/Billiam/promise.lua)