2016-08-31 3 views
1

나는 항상 ok를 반환하는 비동기 요청 (push)을 수행하는 라이브러리를 사용하고 있습니다. ok 또는 오류 여부에 관계없이 실제 응답으로 콜백을 호출합니다.익명 함수가 호출 될 때까지 어떻게 차단합니까?

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 

이 경우 콜백을 차단하고 동기 요청으로 바꾸기를 기다리고 싶습니다. Task.await과 같은 OTP 기능이 있습니까? 아니면이를 동기식 요청으로 바꾸는 다른 해결책이 있습니까?

당신은 부모 프로세스에 콜백에서 메시지를 보내이 같은 receive을 사용할 수 있습니다
+0

저는 콜백에서 메시지를 보내고 Elixir Slack의 micmus가 제안한대로 차단하려고합니다. – nathany

답변

3

:

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" 

출력 : 당신이 메시지를 보낼 수 있습니다

called push 
executing callback 
callback called 
+0

감사합니다. 나는'make_ref'에 대해 몰랐다. 이것은 내가 결국에 끝난 것이다 : https://github.com/codedge-llc/pigeon/issues/29#issuecomment-243903401 – nathany

0

대신 콜백에서 반환하는과 그런 다음 콜백 외부의 메시지가 계속 될 때까지 기다립니다. 메시지에 고유 한 참조가 포함되어 있는지 확인하고 해당 참조에서 메시지를 기다리는 경우 그렇지 않으면 메시지의 출처를 알 수 없습니다.

# 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") 
관련 문제