|
1 | | -# RBX-Try-Library |
2 | | -A library for controlling the flow of error-prone, interdependent functions. |
| 1 | +# RBX.Lua Try Library |
| 2 | +A library for controlling the flow of error-prone, interdependent functions. [Get a built module on Roblox here.](https://www.roblox.com/library/987135020/Try-Library-from-F3X) |
| 3 | + |
| 4 | +## How to use |
| 5 | +Include the library's Try function by requiring the module. |
| 6 | + |
| 7 | +```lua |
| 8 | +local Try = require(TryLibrary) |
| 9 | +``` |
| 10 | + |
| 11 | +### Try(Function, Arguments...) → Attempt |
| 12 | +This function attempts calling `Function` with the given list of `Arguments...`, and returns an `Attempt`, which :Then and :Catch methods can be chained to. |
| 13 | + |
| 14 | +### Attempt:Then(Function `Callback`) → Attempt |
| 15 | +This method takes a callback of the form `Variant Callback(ReturnValues...)`, and calls it **if the attempt succeeded**, with `ReturnValues...` being the list of values returned in the attempt. The attempt is then returned for chaining. |
| 16 | + |
| 17 | +If the first value in `ReturnValues...` is an `Attempt`, it will be executed and the method will process its return values. This allows for chaining, such as in: |
| 18 | + |
| 19 | +```lua |
| 20 | +Try(Wait, 0.1) |
| 21 | + |
| 22 | + -- Try hashing the time |
| 23 | + :Then(function (Delta, ElapsedTime) |
| 24 | + return Try(Game.HttpService.GetAsync, Game.HttpService, 'http://md5.jsontest.com/?text=' .. Delta) |
| 25 | + end) |
| 26 | + |
| 27 | + -- Try decoding the response |
| 28 | + :Then(function (RawResponse) |
| 29 | + return Try(Game.HttpService.JSONDecode, Game.HttpService, RawResponse) |
| 30 | + end) |
| 31 | + |
| 32 | + -- Print the decoded response data |
| 33 | + :Then(function (Response) |
| 34 | + print('Input:', Response.original, '\nMD5:', Response.md5) |
| 35 | + end) |
| 36 | +``` |
| 37 | + |
| 38 | +### Attempt:Catch([String `Predicates...`], Function `Callback`) → Attempt |
| 39 | +This method takes a callback of the form `Variant Callback(String Error, String Stack, Attempt FailedAttempt)`, and calls it **if the attempt had an error**. Errors can be optionally filtered by providing a list of [patterns which the error should match](http://wiki.roblox.com/index.php?title=String_pattern#Simple_matching), otherwise all errors are caught by the function. Once an attempt's error is caught, it will not be caught by the next chained :Catch method, unless `Callback` itself has an error. The attempt is then returned for chaining. |
| 40 | + |
| 41 | +If the first returned value from the attempt is an `Attempt`, it will be executed and the method will process its errors. |
| 42 | + |
| 43 | +```lua |
| 44 | +Try(Game.HttpService.GetAsync, Game.HttpService, 'http://google.com/fakeurl') |
| 45 | + :Then(function (Data) |
| 46 | + print('Found', Data) |
| 47 | + end) |
| 48 | + |
| 49 | + -- Catch when the URL doesn't exist |
| 50 | + :Catch('HTTP 404', function (Error, Stack, Attempt) |
| 51 | + warn('Not found, error:', Error) |
| 52 | + end) |
| 53 | + |
| 54 | + -- Catch any other error |
| 55 | + :Catch(function (Error, Stack, Attempt) |
| 56 | + warn('Unknown error:', Error) |
| 57 | + end) |
| 58 | +``` |
| 59 | + |
| 60 | +### Attempt:Retry() → Attempt |
| 61 | +This method retries the attempt if it failed, and executes any methods that were chained to it. `Attempt.RetryCount` is incremented each time the attempt is retried, and is reset if a retry succeeds. |
| 62 | + |
| 63 | +You can use this method in combination with an attempt's :Catch method to retry a sequence of interdependent function calls that fail, and even limit the number of, or space out, retries. For example: |
| 64 | + |
| 65 | +```lua |
| 66 | +Try(Game.HttpService.GetAsync, Game.HttpService, 'http://httpstat.us/503') |
| 67 | + :Then(function (Data) |
| 68 | + print('Found', Data) |
| 69 | + end) |
| 70 | + |
| 71 | + -- Catch when the server is having issues and retry |
| 72 | + :Catch('HTTP 503', 'Timeout was reached', function (Error, Stack, Attempt) |
| 73 | + |
| 74 | + -- Limit the number of retries to 3 |
| 75 | + if Attempt.RetryCount < 3 then |
| 76 | + |
| 77 | + -- Space out each retry |
| 78 | + local BackoffTime = Attempt.RetryCount * 3 + 3 |
| 79 | + warn('Retrying in', BackoffTime, 'seconds...') |
| 80 | + wait(BackoffTime) |
| 81 | + |
| 82 | + -- Retry the attempt |
| 83 | + return Attempt:Retry() |
| 84 | + |
| 85 | + -- Give up if retry limit reached |
| 86 | + else |
| 87 | + warn('Failed') |
| 88 | + end |
| 89 | + |
| 90 | + end) |
| 91 | + |
| 92 | + -- Catch any other errors |
| 93 | + :Catch(function (Error, Stack, Attempt) |
| 94 | + warn('Unknown error:', Error) |
| 95 | + end) |
| 96 | +``` |
0 commit comments