mirror of
https://github.com/CFC-Servers/cfc_network_promises.git
synced 2025-03-04 03:03:19 -05:00
116 lines
4.9 KiB
Markdown
116 lines
4.9 KiB
Markdown
|
|
# cfc_network_promises
|
|
Network-based promise library
|
|
|
|
## Requirements
|
|
- [cfc_detached_timer](https://github.com/CFC-Servers/cfc_detached_timer)
|
|
|
|
## Async + Await
|
|
This project implements a C#/javascript style async and await functionality.
|
|
Similarly to Javascript, this is built on top of promises.
|
|
|
|
The `await` function takes a promise, and stops the execution thread until that promise resolves or rejects.
|
|
However, `await` can only be used in an `async` function, defined as `myFunc = async(function( a, b ) /* My code */end)`
|
|
|
|
`async` functions return a promise, and thus can be used in `await` themselves. This allows you to chain async functions as you would with promises.
|
|
|
|
## Usage
|
|
- `NP.net.send( name, ... )`
|
|
Send a net message on `name` containing the varargs `...`, no need for any `net.WriteString` or likewise.
|
|
Returns a promise resolving or rejecting with whatever data returned via `NP.net.receive()`
|
|
**Note:** This function sends more than just the varargs, only receive this with `NP.net.receive()`
|
|
|
|
- `NP.net.sendBlind( name, ... )`
|
|
Similar to `NP.net.send` but it does not wait for a response from the server, the returned promise resolves immediately.
|
|
**Note:** Any data returned by `NP.net.receive` from a blind message is discarded.
|
|
|
|
- `NP.net.receive( name, func )`
|
|
Receive a net message on `name` calling `func`, where func is of the form:
|
|
`function( callingPly, ... )`
|
|
The `...` will be whatever they were in the corresponding `NP.net.send()`
|
|
**Note:** Both send and receive will check if the name is already pooled, and if not, will add it as a network string ( `NP.net.send` will still error if called on client using an unpooled name )
|
|
|
|
- `NP.http.post( url, data, timeout )`
|
|
Post data to a `url`, with an optional `timeout` ( defaulting to 5 seconds ).
|
|
Returns a promise resolving in the form:
|
|
`function( statusCode, jsonData, headers )`
|
|
where jsonData is parsed from the post body, or rejecting in the form:
|
|
`function ( errorStr )`
|
|
**Note:** The url must return in JSON, if the JSON cannot be parsed with `util.JSONToTable()` then the promise will reject.
|
|
|
|
- `NP.http.fetch( url, timeout )`
|
|
Identical to `NP.http.post()` but fetches instead.
|
|
|
|
- `NP.http.request( method, endPoint, params, settings )`
|
|
This is a more in-depth way to make http requests, the arguments are as follows:
|
|
- `method` - One of [these http methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)
|
|
- `endPoint` - The endpoint string to be appended to settings.apiRoot
|
|
- `params` - Parameters for GET, POST, HEAD
|
|
- `settings` - In the following structure:
|
|
```lua
|
|
{
|
|
apiRoot: "http://www.mywebsite.com/",
|
|
apikey: "somesupersecretkey",
|
|
timeout: 5 -- optional
|
|
}
|
|
```
|
|
|
|
- `async( func )`
|
|
Wraps the function `func` in a coroutine, passing any arguments onto it. This is required for `await` to be used.
|
|
The new function will return a promise, which will resolve with any return args of the inner function, or reject with any errors.
|
|
|
|
- `asyncCall( func )`
|
|
Equivalent to calling `async( func )()` but nicer looking.
|
|
|
|
- `await( promise )`
|
|
Halts an enclosing coroutine until the promise resolves/rejects, returns `resolved, ...` where `...` are the return args of the promise, or the error.
|
|
**NOTE:** This MUST be called within an async function.
|
|
|
|
## Example
|
|
Server side:
|
|
```lua
|
|
-- "getData" automatically pooled by this function.
|
|
-- Receive on getData, return the result of fetching the scripting url
|
|
NP.net.receive( "getData", function( ply )
|
|
return NP.http.fetch( "https://cfcservers.org/getData" )
|
|
end )
|
|
|
|
-- Alternative implementation:
|
|
NP.net.receive( "getData", async( function( ply )
|
|
local success, body, status = await( NP.http.fetch( "https://cfcservers.org/getData" ) )
|
|
if success then
|
|
return body, status
|
|
else
|
|
error( "Failed to reach end point" )
|
|
end
|
|
end ) )
|
|
```
|
|
Client side:
|
|
```lua
|
|
-- Send net message, print result or error
|
|
NP.net.send( "getData" ):next( function( body, status, headers )
|
|
-- Success
|
|
print( status ) -- Hopefully 200
|
|
PrintTable( util.JSONToTable( body ) ) -- Some data
|
|
end, function( err )
|
|
-- Failure
|
|
print( "Error: ", err )
|
|
end )
|
|
|
|
-- Alternative implementation:
|
|
asyncCall( function()
|
|
-- Thread is halted until the net send finishes, allowing you to treat it as a synchronous function.
|
|
local success, body, status = await( NP.net.send( "getData" ) )
|
|
if success then
|
|
print( status )
|
|
PrintTable( util.JSONToTable( body ) )
|
|
else
|
|
print( "Error: ", err )
|
|
end
|
|
end )
|
|
```
|
|
|
|
|
|
## Credit
|
|
The deferred library (`lua/network_promises/include/deferred.lua`) was written by [zserge](https://github.com/zserge), [here](https://github.com/zserge/lua-promises), and modified for CFC to support varargs in promise resolves and rejects.
|