콜백 대신 지연 가능한 사용의 이점은 무엇입니까? 작은 예.지연 가능한 대 콜백 인터페이스
# This is Deferrable interface
request = NetworkIO.get
request.callback do |resp|
puts "Job is done"
end
request.errback do |err|
puts "Oh. My name is Forest, Forest Gump"
end
# And this is callback interface
NetworkIO.get do |resp|
if Exception === resp
puts "Oh. My name is Forest, Forest Gump"
else
puts "Job is done!"
end
end
# Or node js style
NetworkIO.get do |err, resp|
if err
puts "Oh. My name is Forest, Forest Gump"
else
puts "Job is done!"
end
end
Deferrable에는 중첩 수준이 2 개 있으며 콜백에는 세 개가 있습니다.
필자가 볼 수 있듯이 Deferrable 객체를 사용하면 예를 들어 errback을 전달하고 콜백 만 정의 할 수 있습니다. 어떤 경우에는 의미가 있기 때문에 코드가 적어지고 코드가 적어지고 코드가 더 읽기 쉽게됩니다.
하지만. 나는 성가신 사건을 한 번 발견했다. 예를 들어,이 가짜 비동기 API가 있습니다. 해야는 콜백 모드
class SomeIO
def find(msg, &blk)
socket.send(msg) do |resp|
blk.call(resp)
end
end
def count(msg, &blk)
find(msg) do |resp|
if Exception === resp
blk.call(resp)
else
cnt = resp.size
blk.call(cnt)
end
end
end
end
에 보이는 방법
class SomeIO
def find(msg)
response = DeferrableResponse.new
req = socket.send(msg)
req.callback do |data|
response.succeed(data)
end
req.errback do |err|
response.fail(err)
end
response
end
def count(msg)
response = DeferrableResponse.new
req = find(msg)
req.callback do |data|
response.succeed(data.size)
end
req.errback do |err|
response.fail(err)
end
response
end
end
심지어 지금은 (내 취향) 약간 청소기를 보인다. 그러나 감사 주관적입니다. 상상해보십시오. 여러분은 비동기식 API보다 synchronouse API를 지원할 것입니다.
class SyncSomeIO < SomeIO
def find(msg, &blk)
fib = Fiber.current
socket.send(msg) do |resp|
fib.resume(resp)
end
res = Fiber.yield
raise res if res === Exception
res
end
end
당신 그래서에게 : 콜백 만 속에서의 싸움은 정말 비동기 작전에 섬유를 호출 할 때 지연 가능 인터페이스를 사용하면, (매우 큰 작업과 지원이 매우 무거운 편이다) 섬유로 연기 응답을 가진 모든 방법을 포장한다 파이버에서 소켓을 감싸고 비동기 코드가 synchronouse가되었습니다. 속에서의 싸움은 정말 당신은 또한 모든 블록 방법을 재정의해야한다고 말했다합니다 : 그것은 작은 변화이지만,
class SomeIO
...
def count(msg, &blk)
find(msg) do |resp|
if Exception === resp
block_given? ? blk.call(resp) : resp
else
cnt = resp.size
block_given? ? blk.call(cnt) : cnt
end
end
end
end
코드의 단지 몇 줄에 API가 모두 동기 및 비동기 모드에서 작동 할 수있다.
이런 큰 소개에 불편을 끼쳐 드려 죄송합니다. (두 분 모두) 읽어 주셔서 감사합니다.
질문과 답변입니다. Deferrable은 사실상 Ruby에서 발생하는 API의 표준입니다. 어쩌면 내가 뭔가를 오해하고, 연기 가능한 방식을 잘못 사용합니까? 어쩌면 콜백 인터페이스 냄새와 나쁜 문제가있어?
추 신 : EventMachine의 MongoDB 드라이버에서 작업 중이므로 지금은 클라이언트에 synchronouse 인터페이스를 추가하기 때문에 모든 것을 썼습니다. 그리고 결국 Deferrables 때문에 콜백에 다시 쓰려고 생각하면서 모든 공용 API에 원숭이 패치를 적용하여 동기화 지원을 추가해야한다는 것을 깨달았습니다. 이것은 당신이이 같은 동기 API를 사용하게됩니다
class DeferrableResponse
def sync
fiber = Fiber.current
callback { |val| fiber.resume(val) }
errback { |err| fiber.resume(err) }
result = Fiber.yield
raise result if result.is_a? Exception
result
end
end
: 당신이 Deferrable
의 인터페이스를 제어하는 경우
을하지만 당신은 할 수 콜백 인터페이스와 같은 일을 :) – fl00r
아마 내가 당신의 질문을 이해하지 못합니다. 좀 더 간결하고 구체적인 것을 물어보기 위해 그것을 다시 말해 줄 수 있습니까? – Jacob
제 질문은 꽤 일반적입니다. API를 사용하면 동기 인터페이스를 지원하기가 더 복잡하고 어려워지면 왜 Deferrables를 사용해야합니까? – fl00r