Add await
and async
keywords to Crystal.
In your shards.yml
:
dependencies:
await_async:
github: anykeyh/await_async
branch: master
Then:
require "await_async"
future = async fetch_something
do_some_computation_now
await future
- Call
async
on any method or block to create aMiniFuture
- Call
await
on anyMiniFuture
to wait for/get the result - Conveniently, you can call
await
on future's array.
Can improve drastically application which relay on blocking IO like web API or file writing.
future = async check_website
begin
await 5.seconds, future
rescue MiniFuture::TimeoutException
# rescue from timeout
end
By default, async!
call the newly created fiber just after creation.
- You can use instead
async
so the fiber won't start now:
future = async! { 1 + 2 }
# At this moment the result is already computed
# future.finished? == true
await future # => 3
# vs
future = async { 1 + 2 }
# Here the result is not computed
# future.finished? == false
await future # Compute now
Usually, use async
if your block is computation intensive and current thread
has IO blocking operation. Use async!
in other cases.
In case of errors, the exception will be raise at await
moment, in the await
thread.
A minimalist version of future. Has finished?
and running?
methods.
I don't use Crystal's Concurrent::Future
class because :nodoc:
.
Because crystal is great for building CLI tools. And CLI deals a lot with files and sockets. And IO performed in main thread are slow.
Usage of Channel
is recommended for complex software, as it offers more patterns.
await/async
is useful to build fast and deliver fast.
- require
await_async/helper
instead ofawait_async
- In the class/module you want to use the methods, add
include AwaitAsync::Helper
. You can also simply callawait/async
directly fromAwaitAsync::Helper
def fetch_websites_async
%w[
www.github.com
www.yahoo.com
www.facebook.com
www.twitter.com
crystal-lang.org
].map do |url|
async! do
HTTP::Client.get "https://#{url}"
end
end
end
# Process the websites concurrently. Start querying another website when the
# first one is waiting for response
await(5.seconds, fetch_websites_async).each do |response|
# ...
end
MIT