Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mt-mods/promise
https://github.com/mt-mods/promise
Last synced: 23 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/mt-mods/promise
- Owner: mt-mods
- License: other
- Created: 2023-04-11T06:35:36.000Z (almost 2 years ago)
- Default Branch: master
- Last Pushed: 2024-09-16T13:20:46.000Z (4 months ago)
- Last Synced: 2024-11-08T17:13:14.253Z (3 months ago)
- Language: Lua
- Size: 220 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: readme.md
- License: license.txt
Awesome Lists containing this project
README
promise library for minetest
![](https://github.com/mt-mods/promise/workflows/luacheck/badge.svg)
![](https://github.com/mt-mods/promise/workflows/test/badge.svg)
[![License](https://img.shields.io/badge/License-MIT-green.svg)](license.txt)
[![Download](https://img.shields.io/badge/Download-ContentDB-blue.svg)](https://content.minetest.net/packages/mt-mods/promise)
[![Coverage Status](https://coveralls.io/repos/github/mt-mods/promise/badge.svg?branch=master)](https://coveralls.io/github/mt-mods/promise?branch=master)# Overview
Features:
* Async event handling
* Utilities for formspec, emerge_area, handle_async, http and minetest.after
* async/await helpers (js example [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function))# Examples
Simple promise and handling:
```lua
-- 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:
```lua
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:
```lua
local http = minetest.request_http_api()
local toJson = function(res) return res.json() endlocal p1 = Promise.http(http, "http://localhost/x"):next(toJson)
local p2 = Promise.http(http, "http://localhost/y"):next(toJson)Promise.all(p1, p2):next(function(values)
local x = values[1]
local y = values[2]
end)
```Wait for multiple async workers:
```lua
local fn = function(x,y)
return x*y
endlocal 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:
```lua
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:
```lua
-- 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.empty()`
Returns an already resolved promise with a `nil` value
## `Promise.all(...)`
Wait for all promises to finish
Example:
```lua
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:
```lua
local p1 = Promise.resolved(5)
local p2 = Promise.new()Promise.race(p1, p2):next(function(v)
assert(v == 5)
end)
```**NOTE**: errors don't get propagated when calling `race` only successful results
## `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:
```lua
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:
```lua
local callback = function(fields)
-- TODO: handle CHG, and other "non-quit" events here
endPromise.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 from `minetest.request_http_api()`
* `url` The url to call
* `opts` Table with options:
* `method` The http method (default: "GET")
* `timeout` Timeout in seconds (default: 10)
* `data` Data to transfer, serialized as json if type is `table`
* `headers` table of additional headersExamples:
```lua
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"):next(function(res)
return res.json()
end):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(res)
return res.text()
end):next(function(result)
assert(result)
end):catch(function(res)
-- something went wrong with the http call itself (no response)
-- dump the raw http response (res.code, res.timeout)
print(dump(res))
end)
```## `Promise.json(http, url, opts?)`
Helper function for `Promise.http` that parses a json response
Example:
```lua
-- call chuck norris api: https://api.chucknorris.io/ and expect json-response
Promise.json(http, "https://api.chucknorris.io/jokes/random"):next(function(joke)
assert(type(joke.value) == "string")
end, function(err)
-- request not successful or response-status not 200
print("something went wrong while calling the api: " .. err)
end)
```## `Promise.mods_loaded()`
Resolved on mods loaded (`minetest.register_on_mods_loaded`)
Example:
```lua
Promise.mods_loaded():next(function()
-- stuff that runs when all mods are loaded
end)
```## `Promise.on_punch(pos, timeout?)`
Resolves when the node at `pos` is hit or throws an error if the timeout (in seconds, default: 5) is reached.
## `Promise.dynamic_add_media(options)`
Dynamic media push
Example:
```lua
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
# async/await with `Promise.async`
Similar to [javascripts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) implementation async/await can be used in lua too with the help of [coroutines](https://www.lua.org/pil/9.1.html)
Example: fetch a joke with async/await
```lua
Promise.async(function(await)
local joke = await(Promise.json(http, "https://api.chucknorris.io/jokes/random"))
assert(type(joke.value) == "string")
-- do stuff here with the joke
end)
```Example: sleep for a few seconds
```lua
Promise.async(function(await)
await(Promise.after(5))
-- 5 seconds passed
end)
````Promise.async` returns a Promise that can be used with `:next` or `await` in another async function, for example:
```lua
Promise.async(function(await)
local data = await(Promise.json(http, "https://my-api"))
return data.value * 200 -- "value" is a number
end):next(function(n)
-- n is the result of the multiplication in the previous function
end)
```Error handling:
```lua
Promise.async(function(await)
-- second result from await is the error if rejected
local data, err = await(Promise.rejected("nope"))
assert(err == "nope")
end)
```Error handling with http/json:
```lua
Promise.async(function(await)
local result, err = await(Promise.json(http, "https://httpbin.org/status/500"))
assert(err == "unexpected status-code: 500")
end)
```# License
* Code: MIT (adapted from https://github.com/Billiam/promise.lua)
![Yo dawg](yo.jpg)