2013-02-21 2 views
0

아약스 호출에서 지연된 개체를 반환하는 중첩 함수가 여러 개 있습니다. 내 코드는 다음과 같습니다.jQuery 지연된 개체 : .when() s, .then() 및 .done() s와의 예기치 않은 동작 s

function makeCalls() { 
    var ajaxDfd1 = $.ajax(...); 

    ajaxDfd1.then(function() { 
     // want to execute after first call 
     var ajaxDfd2 = $.ajax(...); 

     ajaxDfd2.done(function() { 
      // want to execute after second call 
     }); 

     return ajaxDfd2; 
    }); 

    return ajaxDfd1; 
} 

makeCalls().done(function() { 
    // stuff here was executed early 
}); 

그러나 내 전화가 의도 한 순서대로 실행되고 있지 않습니다. 안에있는 내용은 makeCalls().done() 전에 호출 된 것 같습니다 ajaxDfd2 실제로 이루어집니다.

답변

0

내가 뭔가 잘못을 받고해야 알고,이 쳐다보고 정말로 긴 시간을 보냈다 : When should I use jQuery deferred's "then" method and when should I use the "pipe" method?

나중에 내가이 실제로하지 않습니다

var dfdObj = $.ajax(...); 
dfdObj.then(...); 

return dfdObj; 

할 수없는 것을 깨달았 지연된 객체를 반환합니다. Ajax 객체를 반환하고 일반 객체이므로 자동으로 해결됨으로 분류되어 .done() 함수가 일찍 호출되었습니다. 나는 var

var dfdObj = $.ajax(...).then(...); 

return dfdObj; 
2

초코을 반환 할 경우 대신, 당신은 당신의 대답에 잘못된 가정을했습니다

,이 작업을 수행 할 필요가; 즉 $.ajax()은 "일반 개체"를 반환합니다.

정확하지 않습니다.

$.ajax()은 Promise의 상위 집합 인 jqXHR 객체를 반환합니다. Promise의 모든 메소드와 AJAX에 고유 한 메소드 (예 : .abort())가 있습니다.

$.ajax()에 의해 반환 된 개체가 Promise와 호환되지 않는 경우 질문에있는 코드는 makeCalls().done(...)을 실행하려고하면 오류가 발생합니다.

.done() 함수가 먼저 실행되어 그 함수가 바깥 쪽jqXHR을 반환하는 이유는 다음과 같습니다.

function makeCalls() { 
    var dfrd = new Deferred(); 
    $.ajax(...).then(function() { 
     $.ajax(...).done(dfrd.resolve); 
    }); 
    return dfrd.promise(); 
} 

makeCalls().done(function(data) { 
    // ... 
}); 

또는

function makeCalls(fn) { 
    $.ajax(...).then(function() { 
     $.ajax(...).done(fn); 
    }); 
} 

makeCalls(function(data) { 
    // ... 
}); 

당신은 시도조차 할 수 :

function makeCalls() { 
    return $.ajax(...).then(function() { 
     return $.ajax(...); 
    }); 
} 

makeCalls().done(function() { 
    // ... 
}); 
+0

. 마지막 하나는 완벽합니다. – Bergi

+0

@Bergi, 왜 당신이 그 이유를 설명 할 수 있을지 확신합니다! –

+0

처음은 지나치게 복잡하기 때문에 -'then' (이미 사용하고있는 것)은 수동으로하는 일을 정확히 수행합니다. 두 번째는 Deferreds를 사용하지 않았기 때문에 요청되지 않은 콜백 (CPS를 대체하기위한 약속)이 있습니다. – Bergi

0

귀하의 코드는 다음과 같이 작동 여기

당신이 기대했던 동작을 달성하기 위해 몇 가지 방법입니다 :

function makeCalls() { 
    var ajax1 = $.ajax(…); 
    var ajax1and2 = ajax1.then(makeCall2); 
    function makeCall2() { 
     // want to execute after first call 
     var ajax2 = $.ajax(…); 
     ajax2.done(after2); 
     function after2() { 
      // want to execute after second call 
     }); 
     return ajax2; 
    }); 
    return ajax1; 
} 

var ajax1 = makeCalls(); 
ajax1.done(function() { 
    // stuff here was executed early 
}); 

ajax1and2then/pipe 전화로 얻은 결과입니다. 콜백하면 makeCall2 (즉, ajax2)의 결과가 ajax1이 될 때까지 대기합니다. after2 콜백과 같습니다.

그러나, 당신의 makeCalls 기능은 ajax1 객체를 반환 (당신은 나뿐만 아니라 글로벌 ajax1 변수에 할당 볼 수 있습니다)와 모두 makeCall2 및 첫 번째 아약스가 완료되면 완료 콜백이 실행됩니다.

그래서, 대신 반환해야 할 ajax1and2 연기 : 내가 처음 두 가지 버전 중 하나를 권하고 싶지 않다

function makeCalls() { 
    return $.ajax(…).then(function() { 
     return $.ajax(…).done(function() { 
      // want to execute after second call 
     }); 
    }); 
} 

makeCalls().done(function() { 
    // stuff here is now executed after second call as well 
}); 
관련 문제