Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kevinhwang91/promise-async

Promise & Async in Lua
https://github.com/kevinhwang91/promise-async

async async-await eventloop libuv lua luv neovim promise

Last synced: about 2 hours ago
JSON representation

Promise & Async in Lua

Awesome Lists containing this project

README

        

# promise-async

![GitHub Test](https://github.com/kevinhwang91/promise-async/workflows/Test/badge.svg)
![GitHub Lint](https://github.com/kevinhwang91/promise-async/workflows/Lint/badge.svg)

The goal of promise-async is to port [Promise][promise] & [Async][async] from JavaScript to Lua.

> A value returned by async function in JavaScript is actually a Promise Object. It's incomplete and
> inflexible for using an async function wrapped by bare coroutine without Promise in almost Lua
> implementation.

- [Features](#features)
- [Demonstration](#demonstration)
- [Script](#script)
- [demo.lua](#demo.lua)
- [demo.js](#demo.js)
- [Quickstart](#quickstart)
- [Requirements](#requirements)
- [Installation](#installation)
- [As a plugin for Neovim platform](#as-a-plugin-for-neovim-platform)
- [As a library from Luarocks](#as-a-library-from-luarocks)
- [Documentation](#documentation)
- [Summary](#summary)
- [async](#async)
- [Development](#development)
- [Neovim tips](#neovim-tips)
- [Run tests](#run-tests)
- [Improve completion experience](#improve-completion-experience)
- [Customize EventLoop](#customize-eventloop)
- [Credit](#credit)
- [Feedback](#feedback)
- [License](#license)

## Features

- API is similar to JavaScript's
- Customize EventLoop in any platforms
- Support Lua 5.1-5.4 and LuaJIT with an EventLoop module
- Support Neovim platform

## Demonstration

### Script

#### demo.lua

#### demo.js

## Quickstart

### Requirements

- Lua 5.1 or latter
- [Luv](https://github.com/luvit/luv)

> Luv is a default EventLoop for promise-async. It doesn't mean promise-async must require it. In
> fact, promise-async require a general EventLoop module which Luv like.

### Installation

#### As a plugin for Neovim platform

Install with [Packer.nvim](https://github.com/wbthomason/packer.nvim):

- As a normal plugin

```lua
use {'kevinhwang91/promise-async'}
```

or

- As a Luarocks plugin

```lua
use_rocks {'promise-async'}
```

#### As a library from Luarocks

1. `luarocks install promise-async`
2. `luarocks install luv` or implement an EventLoop
[interface](https://github.com/kevinhwang91/promise-async/blob/main/typings/loop.lua) to adapt
your platform

## Documentation

promise-async's API is based on [MDN-Promise][promise]. [typings/promise.lua](typings/promise.lua)
is the typings with documentation of Promise class.

### Summary

Summary up the API different from JavaScript.

| JavaScript | Lua |
| --------------------------------------------------- | ----------------------------------------------- |
| `new Promise` | `Promise:new`/`Promise` |
| `Promise.then` | `Promise:thenCall`, `then` is language keyword |
| `Promise.catch` | `Promise:catch` |
| `Promise.finally` | `Promise:finally` |
| `Promise.resolve` | `Promise.resolve` |
| `Promise.reject` | `Promise.reject` |
| `Promise.all`: `Symbol.iterator` as iterator | `Promise.all`: `pairs` as iterator |
| `Promise.allSettled`: `Symbol.iterator` as iterator | `Promise.allSettled`: `pairs` as iterator |
| `Promise.any`: `Symbol.iterator` as iterator | `Promise.any`: `pairs` as iterator |
| `Promise.race`: `Symbol.iterator` as iterator | `Promise.race`: `pairs` as iterator |
| `async`: as keyword at the start of a function | `Async`/`Async.sync`: as a surrounding function |
| `await`: as keyword | `await`/`Async.wait` as a function |

### async

The environment in `Async.sync` function have been injected some new functions for compatibility or
enhancement:

1. `await`: A reference of `Async.wait` function;
2. `pcall`: Be compatible with LuaJIT;
3. `xpcall`: Be compatible with LuaJIT;

`async` in JavaScript return Promise object only with single result, but may carry multiple results
in Lua. The resolved result of Promise object return by `async` function will be packed into a table
via `{...}`. However, the result handled by `await` will be unpacked and return multiple values.

```lua
local async = require('async')

local function f()
return 1, 2, 3
end

-- multiple results are packed into resolved result in Promise
async(f):thenCall(function(v)
print(v[1], v[2], v[3]) -- output: 1 2 3
end)

-- results returned by `await`
async(function()
local v1, v2, v3 = await(async(f))
print(v1, v2, v3) -- output: 1 2 3
end)

uv.run()
```

## Development

### Neovim tips

- `Promise.resolve():thenCall(cb)` is almost equivalent to `vim.schedule(cb)`.

### Run tests

`make test`

### Improve completion experience

Following [typings/README.md](./typings/README.md)

### Customize EventLoop

TODO, refer to [loop.lua](./lua/promise-async/loop.lua)

## Credit

- [Promise][promise]
- [Async][async]
- [promises-tests](https://github.com/promises-aplus/promises-tests)
- [then/promise](https://github.com/then/promise)
- [promisejs.org](https://www.promisejs.org)
- [event-loop-timers-and-nexttick](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick)

[promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
[async]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

## Feedback

- If you get an issue or come up with an awesome idea, don't hesitate to open an issue in github.
- If you think this plugin is useful or cool, consider rewarding it a star.

## License

The project is licensed under a BSD-3-clause license. See [LICENSE](./LICENSE) file for details.