async function bar(){...}
function baz() {...}
async function foo() {
var x = await bar();
var y = baz();
return x, y;
}
Lua: function bar() return something_that_may_yield_deep_inside(...) end
function baz() ... end
function foo()
local x = bar()
local y = baz()
return x, y
end
Iow, in Lua it is irrelevant whether something yields or not, so you don’t care if it is async.If a sub-sub-sub-function suddenly decides to yield, you might not even know that your whole path is waiting for that. Right? Perhaps you need baz() to run asap but that isn't clear without looking deep into bar().
When I see
var x = await bar();
I know that other code, outside bar(), may have run during the execution of that statement.Also, the JS approach makes composing asynchronous operations simple:
var x = bar();
var y = bar();
return await x, await y;
Both bar invocations can run in parallel. If, say, each invocation of bar fires off an Ajax request that takes a few seconds to come back, that can be a significant saving.It's unclear (to me) how that would be done in Lua without complicating the API.
local requests = { "/mysql", "/postgres", "/redis", "/memcached" }
local responses = { ngx.location.capture_multi(requests) }
for i, response in ipairs(responses) do
print(response.foobar)
end
But instead ngx could lazy-evaluate responses with help of metatables (see my other comment).Also lua-like stackfull coroutines don't prevent firing multiple asynchronous operations at the same time (like in your example), they only make the waiting much more peasant.
>Promise.all()
Objects returned from yields_deep_inside() may be implemented as lazy-evaluated, i.e. only `print(result.items)` or explicit `await(result)` will yield upon use, while request will be sent immediately. Thus the order of execution will depend purely on natural use case, not on programmed await sequences/groups. Since js is not parallel, you'll touch A or B first, not both.
How to sort it all out is a responsibility of an event framework, not of green thread abstraction that is coroutine.
One more thing: idk how js optimizes endless closures that are spawned as promise callbacks, but Lua coroutine's yield/resume is as cheap as return from / pass control to a VM. No closures are created to retain state across async calls, because VM stack is state itself. I suspect wrapping everything in async-await will simply trash GC and VM performance. In a sense, asynchrony is only emulated in javascript with a cost, though I may be wrong and it all is optimized out. We have to wait for jsvm implementation experts to [dis]prove that.