콜백지옥은 어떤 연산이 다른 연산에 종속적일 때, 콜백 안에 콜백이 들어가는 것을 말하고, 차례대로 발생해야 하는 비동기 호출이 세 개 있을 때는 자바스크립트 코드에서 보는 것처럼 세 단계의 콜백을 구현한다.
api_call1(request1, function(response1) {
// 1단계
var request2 = step1(response1);
api_call2(request2, function (reponse2) {
// 2단계
var request 3 = step2(response2);
api_call3(request3, function (response3) {
// 3단계
step 3(response3)'
api_call1(), api_call2(), api_call3()는 결과를 비동기식으로 가져오기 위해 사용하는 라이브러리 함수로, 각 라이브러리 함수는 콜백 함수를 받고 응답 처리를 하는 일반적인 함수를 나타난다.
#파이썬에서 콜백 지옥
def stage1(response1):
request2 = step1(response1)
api_call2(request2, stage2)
def stage2(response2):
request3 = step2(response2)
api_call3(request3, stage3)
def stage3(response3):
step(response3)
api_call1(request1, stage1)
세 개의 비동기 작업을 연속으로 처리하기 위해서 코루틴 체인에서 yield를 세 번 사용해서 이벤트 루프가 계속 실행할 수 있게 하여, 결과가 나오면 코루틴의 send() 메서드를 호출해서 코루틴을 활성화하면 된다.
이벤트 루프의 관점에서 보면 send() 메서드 호출과 콜백 메서드 호출은 비슷하지만 코루틴 스타일의 비동기 API를 사용하는 입장에서 보면 상황은 더 좋고, 하나의 함수 안에서 전체 작업의 콘텍스트를 지역 변수 안에 넣고, 일반적인 함수를 호출하듯이 연속으로 세 개의 함수를 호출하면 된다.
@asyncio.coroutine
def three_stages(request1):
response1 = yield form api_call1(request1)
#1단계
request2 = step1(response1)
response2 = yield from api_call2(request2)
#2단계
request3 = step2response2
response3 = yield from api_call3(request3)
#3단계
step3(response3)
loop.create_task(three_stages(request1)) #명시적으로 실행을 스케쥴
코루틴은 천국이 아니다.
첫 번째 장애물: 일반 함수 대신 반드시 코루틴을 사용해야 하고, yield from 에 익숙해져아 한다.