Reputation: 549
I'm using a library that does an asynchronous request (push
) that always returns ok. It calls a callback with the actual response, whether ok or an error.
callback = fn(response) ->
# handle error or ok
end
:ok = Pigeon.APNS.push(n, callback)
# push returns immediately, but I want to block
# until callback is called and return that response
In this case I want to block and wait for the callback, turning this into a synchronous request. Is there an OTP feature like Task.await
or some other solution to turn this into a synchronous request?
Upvotes: 1
Views: 484
Reputation: 12085
Instead of returning from the callback you can send a message and then wait for the message outside the callback to continue. Make sure the message contains a unique reference and you are waiting for a message from that reference otherwise you won't know where the message is coming from.
# Create a unique reference so you know
# where the return is coming from
id = make_ref()
# A function for waiting until a value
# comes in from a reference
wait_for_response = fn (id) ->
receive do
{^id, val} -> val
end
end
callback = fn (val) ->
IO.puts("In Callback")
# instead of returning, send the value to self with
# the right reference
send(self, {id, "I was passed the argument #{inspect val}"})
end
# Async fun knows nothing about this diferment
# and functions as normal
async_fun = fn (i, cb) ->
IO.puts("In Async Function")
Process.sleep(2000)
cb.(i)
end
# Usage
IO.puts("Starting")
async_fun.(1, callback)
val = wait_for_response.(id)
IO.puts "Callback returned: #{inspect val}"
IO.puts("All Done")
Upvotes: 0
Reputation: 222128
You can send a message from the callback to parent process and use receive
like this:
defmodule Pigeon.APNS do
def push(_n, callback) do
spawn_link(fn ->
:timer.sleep(2000)
callback.(:ok)
end)
:ok
end
end
ref = make_ref()
pid = self()
callback = fn(_response) ->
IO.puts "executing callback"
send(pid, ref)
end
:ok = Pigeon.APNS.push(0, callback)
IO.puts "called push"
receive do
^ref -> :ok
end
IO.puts "callback called"
Output:
called push
executing callback
callback called
Upvotes: 3