|
1 | | -*lua-async-await.txt* For Neovim >= 0.9.4 Last change: 2023 December 10 |
| 1 | +*lua-async-await.txt* For Neovim >= 0.9.4 Last change: 2024 March 31 |
2 | 2 |
|
3 | 3 | ============================================================================== |
4 | 4 | Table of Contents *lua-async-await-table-of-contents* |
5 | 5 |
|
6 | | -1. Lua Async Await |lua-async-await-lua-async-await| |
7 | | - - Why? |lua-async-await-why?| |
| 6 | +1. Lua Async |lua-async-await-lua-async| |
| 7 | + - What |lua-async-await-what| |
| 8 | + - Why |lua-async-await-why| |
8 | 9 | - How to use |lua-async-await-how-to-use| |
9 | 10 |
|
10 | 11 | ============================================================================== |
11 | | -1. Lua Async Await *lua-async-await-lua-async-await* |
| 12 | +1. Lua Async *lua-async-await-lua-async* |
12 | 13 |
|
13 | | -This is basically ms-jpq/lua-async-await |
14 | | -<https://github.com/ms-jpq/lua-async-await> but with Promise like error |
15 | | -handling |
| 14 | +Synchronous like asynchronous for Lua. |
16 | 15 |
|
17 | | -Refer the original repository for more comprehensive documentation on how all |
18 | | -this works |
19 | 16 |
|
| 17 | +WHAT *lua-async-await-what* |
20 | 18 |
|
21 | | -WHY? *lua-async-await-why?* |
| 19 | +Take a look at before and after |
22 | 20 |
|
23 | | -A Language Server command response contains two parameters. `error` & |
24 | | -`response`. If the error is present then the error should be handled. |
25 | | - |
26 | | -Ex:- |
| 21 | +**Before:** |
27 | 22 |
|
28 | 23 | >lua |
29 | | - self.client.request('workspace/executeCommand', cmd_info, function(err, res) |
| 24 | + request('workspace/executeCommand', cmd_info, function(err, res) |
30 | 25 | if err then |
31 | | - log.error(command .. ' failed! arguments: ', arguments, ' error: ', err) |
| 26 | + log.error(err) |
32 | 27 | else |
33 | | - log.debug(command .. ' success! response: ', res) |
| 28 | + log.debug(res) |
34 | 29 | end |
35 | 30 | end, buffer) |
36 | 31 | < |
37 | 32 |
|
38 | | -Promises are fine but chaining is annoying specially when you don’t have |
39 | | -arrow function like syntactic sugar. Moreover, at the time of this is writing, |
40 | | -Lua language server generics typing is so primitive and cannot handle |
41 | | -`Promise<Something>` like types. |
| 33 | +**After:** |
| 34 | + |
| 35 | +>lua |
| 36 | + -- on error, statement will fail throwing an error just like any synchronous API |
| 37 | + local result = request('workspace/executeCommand', cmd_info, buffer) |
| 38 | + log.debug(result) |
| 39 | +< |
| 40 | + |
42 | 41 |
|
43 | | -So I wanted Promise like error handling but without Promises. |
| 42 | +WHY *lua-async-await-why* |
44 | 43 |
|
| 44 | +Well, callback creates callback hell. |
45 | 45 |
|
46 | | -HOW TO USE *lua-async-await-how-to-use* |
47 | 46 |
|
48 | | -Assume following is the asynchronous API |
| 47 | +HOW TO USE *lua-async-await-how-to-use* |
49 | 48 |
|
50 | 49 | >lua |
51 | | - local function lsp_request(callback) |
| 50 | + local runner = require("async.runner") |
| 51 | + local wrap = require("async.wrap") |
| 52 | + local wait = require("async.waits.wait_with_error_handler") |
| 53 | + |
| 54 | + local function success_async(callback) |
52 | 55 | local timer = vim.loop.new_timer() |
53 | 56 |
|
54 | 57 | assert(timer) |
55 | 58 |
|
56 | 59 | timer:start(2000, 0, function() |
57 | 60 | -- First parameter is the error |
58 | | - callback('something went wrong', nil) |
| 61 | + callback(nil, "hello world") |
59 | 62 | end) |
60 | 63 | end |
61 | | -< |
62 | | - |
63 | | - |
64 | | -WHEN NO ERROR HANDLER DEFINED ~ |
65 | | - |
66 | | -This is how you can call this asynchronous API without a callback |
67 | | - |
68 | | ->lua |
69 | | - local M = require('sync') |
70 | 64 |
|
71 | | - M.sync(function() |
72 | | - local response = M.wait_handle_error(M.wrap(lsp_request)()) |
73 | | - end).run() |
74 | | -< |
75 | | - |
76 | | -Result: |
77 | | - |
78 | | -> |
79 | | - Error executing luv callback: |
80 | | - test6.lua:43: unhandled error test6.lua:105: something went wrong |
81 | | - stack traceback: |
82 | | - [C]: in function 'error' |
83 | | - test6.lua:43: in function 'callback' |
84 | | - test6.lua:130: in function <test6.lua:129> |
85 | | -< |
86 | | - |
87 | | - |
88 | | -WHEN ERROR HANDLER IS DEFINED ~ |
89 | | - |
90 | | ->lua |
91 | | - local M = require('sync') |
| 65 | + local function fail_async(callback) |
| 66 | + local timer = vim.loop.new_timer() |
92 | 67 |
|
93 | | - local main = M.sync(function() |
94 | | - local response = M.wait_handle_error(M.wrap(lsp_request)()) |
95 | | - end) |
96 | | - .catch(function(err) |
97 | | - print('error occurred ', err) |
| 68 | + assert(timer) |
| 69 | + |
| 70 | + timer:start(2000, 0, function() |
| 71 | + -- First parameter is the error |
| 72 | + callback("something went wrong", nil) |
98 | 73 | end) |
99 | | - .run() |
100 | | -< |
101 | | - |
102 | | -Result: |
103 | | - |
104 | | -> |
105 | | - error occurred test6.lua:105: something went wrong |
106 | | -< |
107 | | - |
108 | | - |
109 | | -WHEN NESTED ~ |
110 | | - |
111 | | ->lua |
112 | | - local M = require('sync') |
| 74 | + end |
113 | 75 |
|
114 | | - local nested = M.sync(function() |
115 | | - local response = M.wait_handle_error(M.wrap(lsp_request)()) |
116 | | - end) |
| 76 | + local function log(message) |
| 77 | + vim.print(os.date("%H:%M:%S") .. " " .. message) |
| 78 | + end |
| 79 | + |
| 80 | + vim.cmd.messages("clear") |
117 | 81 |
|
118 | | - M.sync(function() |
119 | | - M.wait_handle_error(nested.run) |
| 82 | + local nested = runner(function() |
| 83 | + local success_sync = wrap(success_async) |
| 84 | + local fail_sync = wrap(fail_async) |
| 85 | + |
| 86 | + local success_result = wait(success_sync()) |
| 87 | + -- here we get the result because there is no error |
| 88 | + log("success_result is: " .. success_result) |
| 89 | + |
| 90 | + -- following is going to fail and error will get caught by |
| 91 | + -- the parent runner function's 'catch' |
| 92 | + wait(fail_sync()) |
120 | 93 | end) |
| 94 | + |
| 95 | + runner(function() |
| 96 | + log("starting the execution") |
| 97 | + -- just wait for nested runner to complete the execution |
| 98 | + wait(nested.run) |
| 99 | + end) |
121 | 100 | .catch(function(err) |
122 | | - print('parent error handler ' .. err) |
| 101 | + log("parent error handler " .. err) |
123 | 102 | end) |
124 | 103 | .run() |
125 | 104 | < |
126 | 105 |
|
127 | | -Result: |
128 | 106 |
|
129 | | -> |
130 | | - parent error handler test6.lua:105: test6.lua:105: something went wrong |
| 107 | +OUTPUT ~ |
| 108 | + |
| 109 | +>txt |
| 110 | + 18:44:46 starting the execution |
| 111 | + 18:44:48 success_result is: hello world |
| 112 | + 18:44:50 parent error handler ...-async-await/lua/async/waits/wait_with_error_handler.lua:14: ...-async-await/lua/async/waits/wait_with_error_handler.lua:14: something went wrong |
131 | 113 | < |
132 | 114 |
|
133 | 115 | Generated by panvimdoc <https://github.com/kdheepak/panvimdoc> |
|
0 commit comments