Network-based promise library
Go to file
Samuel Williams 3d67ef6dca Update lua/network_promises/async.lua
Co-authored-by: Brandon Sturgeon <sturgeonb4@gmail.com>
2021-07-08 19:25:21 -07:00
lua Update lua/network_promises/async.lua 2021-07-08 19:25:21 -07:00
.gitignore Add gitignore 2021-07-09 02:56:11 +01:00
LICENSE Initial commit 2020-02-15 16:13:23 -08:00
README.md Add dTimer dependency 2021-01-16 22:34:21 +00:00

cfc_network_promises

Network-based promise library

Requirements

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
    • endPoint - The endpoint string to be appended to settings.apiRoot
    • params - Parameters for GET, POST, HEAD
    • settings - In the following structure:
      {
        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:

    -- "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:

    -- 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, here, and modified for CFC to support varargs in promise resolves and rejects.