2013-11-21 3 views
13

동기 및 비동기 함수를 특정 순서로 실행하려면 jQuery 약속을 사용할 수는 있지만 예상대로 작동하지 않는 것처럼 보입니다. 작업.jQuery 지연 및 동기 및 비동기 함수의 순차적 실행에 대한 약속

deferred.resolve() 함수가 호출 될 때 함수 a, b 및 c가 순서대로 실행되어야 함에도 불구하고 함수 b가 실행되기를 기대하지만 resolve가 호출 되더라도 모든 함수가 즉시 실행됩니다.

function a(){ 
    var deferred = $.Deferred(); 
    setTimeout(function(){ 
    console.log("status in a:",deferred.state()); 
    //this should trigger calling a or not? 
    deferred.resolve("from a"); 
    },200); 
    console.log("a"); 
    return deferred.promise(); 
}; 
function b(){ 
    var deferred = $.Deferred(); 
    setTimeout(function(){ 
    console.log("status in b:",deferred.state()); 
    deferred.resolve("from b"); 
    },200); 
    console.log("b"); 
    return deferred.promise(); 
} 
//synchronous function 
function c(){ 
    var deferred = $.Deferred(); 
    console.log("c"); 
    console.log("status in c:",deferred.state()); 
    deferred.resolve("from c"); 
    return deferred.promise(); 
} 
function test(){ 
    fn=[a,b,c],i=-1, 
    len = fn.length,d, 
    d = jQuery.Deferred(), 
    p=d.promise(); 
    while(++i<len){ 
    p=p.then(fn[i]); 
    } 
    p.then(function(){ 
    console.log("done"); 
    }, 
    function(){ 
    console.log("Failed"); 
    }); 
    d.resolve(); 
    //instead of the loop doing the following has the same output 
    //p.then(a).then(b).then(c); 
    //d.resolve(); 
} 
test(); 

출력된다 :

a 
b 
status in c: pending 
c 
done 
status in a: pending 
status in b: pending 

예상 출력 :

a 
status in a: pending 
b 
status in b: pending 
c 
status in c: pending 
done 

다음 변형의 일부 조합을 시도 :

d = jQuery.Deferred(); 
    setTimeout(function(){d.resolve();},100); 
    var p=d.promise(); 
    while(++i<len){ 
    p.then(fn[i]); 
    } 
여기

는 코드

그러나 예기치 않은 동일한 결과가 모두 나오면 b는 a의 지연이 해결되기 전에 호출되고 c는 b의 지연이 해결되기 전에 호출됩니다.

답변

9

jQuery를 들어 이전에 1.8,이 문제이지만, jQuery를 새로운 버전이 더 이상 문제가되지 않습니다 :

function test(){ 
    var d = jQuery.Deferred(), 
    p=d.promise(); 
    //You can chain jQuery promises using .then 
    p.then(a).then(b).then(c); 
    d.resolve(); 
} 
test(); 
다음

DEMO

jQuery를 1.7.2의 데모입니다

DEMO

+1

부수적으로 jquery 1.7.2에서 작동하려면 (jq 확장 코드 사용) http://jsfiddle.net/L5nud/2/ –

+1

jQuery <1.8은 괜찮습니다. WRT 체인을 사용하면 .pipe를 사용할 수 있습니다. .then 대신. 1.8 단순히 변경. 다음 .pipe 수 있습니다. – Esailija

+0

'a' 함수가'b' 함수를 사용하는 값을 반환하는 등의 경우 사용법을 설명합니다. –

2

jQuery를이 < 1.8 미세 WRT 체인은, 당신은 단지 .pipe 대신 01를 사용한다. 1.8은 단순히 .then.pipe으로 변경했습니다.

1

Sidenote : 배열없이 사용하면 약속을 시작할 필요가 없습니다. $.when({}).then(a).then(b) 트릭을 잘 할 것입니다. when 안에 a을 넣지 않아야합니다.

관련 문제