2020-02-15 20:51:41 -05:00
2020-02-15 19:13:23 -05:00
# cfc_network_promises
Network-based promise library
2020-02-15 20:51:41 -05:00
2021-01-16 17:24:06 -05:00
## Requirements
- [cfc_detached_timer ](https://github.com/CFC-Servers/cfc_detached_timer )
2020-02-24 20:37:26 -05:00
## 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.
2020-02-15 20:51:41 -05:00
## Usage
2020-02-15 20:54:18 -05:00
- `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()`
2020-02-15 20:51:41 -05:00
2020-02-24 20:37:26 -05:00
- `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.
2020-02-15 20:54:18 -05:00
- `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 )
2020-02-15 20:51:41 -05:00
2020-02-15 20:54:18 -05:00
- `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.
2020-02-15 20:51:41 -05:00
2020-02-15 20:54:18 -05:00
- `NP.http.fetch( url, timeout )`
Identical to `NP.http.post()` but fetches instead.
2020-02-15 20:51:41 -05:00
2020-02-24 20:37:26 -05:00
- `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.
2020-02-15 20:51:41 -05:00
## Example
Server side:
```lua
2020-02-15 20:54:18 -05:00
-- "getData" automatically pooled by this function.
2020-02-25 18:10:59 -05:00
-- Receive on getData, return the result of fetching the scripting url
2020-02-15 20:54:18 -05:00
NP.net.receive( "getData", function( ply )
2020-02-25 18:10:59 -05:00
return NP.http.fetch( "https://cfcservers.org/getData" )
2020-02-15 20:54:18 -05:00
end )
2020-02-24 20:37:26 -05:00
-- Alternative implementation:
NP.net.receive( "getData", async( function( ply )
2020-02-25 18:10:59 -05:00
local success, body, status = await( NP.http.fetch( "https://cfcservers.org/getData" ) )
2020-02-24 20:37:26 -05:00
if success then
2020-02-25 18:10:59 -05:00
return body, status
2020-02-24 20:37:26 -05:00
else
error( "Failed to reach end point" )
end
end ) )
2020-02-15 20:51:41 -05:00
```
Client side:
```lua
2020-02-15 20:54:18 -05:00
-- Send net message, print result or error
2020-02-25 18:10:59 -05:00
NP.net.send( "getData" ):next( function( body, status, headers )
2020-02-15 20:54:18 -05:00
-- Success
print( status ) -- Hopefully 200
2020-02-25 18:10:59 -05:00
PrintTable( util.JSONToTable( body ) ) -- Some data
2020-02-15 20:54:18 -05:00
end, function( err )
-- Failure
print( "Error: ", err )
end )
2020-02-24 20:37:26 -05:00
-- Alternative implementation:
asyncCall( function()
-- Thread is halted until the net send finishes, allowing you to treat it as a synchronous function.
2020-02-25 18:10:59 -05:00
local success, body, status = await( NP.net.send( "getData" ) )
2020-02-24 20:37:26 -05:00
if success then
print( status )
2020-02-25 18:10:59 -05:00
PrintTable( util.JSONToTable( body ) )
2020-02-24 20:37:26 -05:00
else
print( "Error: ", err )
end
end )
2020-02-15 20:51:41 -05:00
```
2020-02-24 20:37:26 -05:00
2020-02-15 20:51:41 -05:00
## 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.