2013-11-21 96 views
13

如果我想有一個特定的順序執行同步和異步函數我可以使用jQuery的承諾,但它似乎並沒有按照我所期望的方式工作工作。jQuery延遲和承諾順序執行的同步和異步功能

在調用deferred.resolve()函數時,函數a,b和c應按順序執行我期望函數b被執行,但所有函數都會立即執行,無論調用何時執行。

下面是代碼:

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而不是。 1.8簡單地改變,然後是.pipe。 – Esailija

+0

如何使用它,如果'a'函數返回一個使用'b'函數的值等等。 –

2

jQuery的< 1.8被罰款WRT鏈接,您只需使用.pipe而不是.then。 1.8簡單地將.then更改爲.pipe

1

旁註:當你在沒有數組的情況下使用它時,你不必從承諾開始。 $.when({}).then(a).then(b)將會訣竅。你只需要確保你不要把a放在when之內。