2011-04-20 59 views
4

我要打電話三種功能someTask1someTask2並依次someTask3。然而,功能someTask2涉及Ajax調用,並保持自稱遞歸使用setTimeout除非所需價值回報。代碼如下所示:連續函數調用,而其中一人使用的setTimeout

doListOfTasks: function(myparam){ 
    var someObj = someTask1(myParam); 
    someTask2(someObj); 
    someTask3(someObj); 
}, 
someTask2: function(someObj){ 
    $.ajax({ 
      url: "someUrl.do", 
      type: "POST", 
      data: ({"id": rowObject.instanceId}), 
      dataType: "json", 
      async:false, 
      success: function(res){ 
       if(res.prop1 != 'desired'){ 
        setTimeout(function(){someTask2(someObj);}, 2000); 
       } 
      } 
     } 
    ); 
}, 

正如你可能已經猜到了,這個代碼的執行不會等待someTask2調用someTask3之前返回。

我想裏面doListOfTasks代碼順序執行。我怎樣才能做到這一點?

而且,我不想硬編碼someTask3success回調。例如。我不想這樣做:

  success: function(res){ 
       if(res.prop1 != 'desired'){ 
        setTimeout(function(){someTask2(someObj);}, 2000); 
       }else{ 
        someTask3(someObj); 
       } 

      } 

怎麼能做到這一點?

感謝


編輯#1

的問題是不能夠調用的函數......但問題是同步的。我想someTask2完成不管它在做什麼,並才把someTask3被調用。

someTask2調用自己重複使用setTimeout ...我想這會觸發一個新的線程和someTask2是第一次調用後返回...觸發someTask3在主線程。然而,在每個調用setTimeout中,獨立的線程會產生(並被殺死),直到滿足所需的條件。

這就是爲什麼,而someTask2仍然循環,調用someTask3觸發。

不知道我有多正確。

+0

你基本上是正確的,雖然JavaScript的只有一個執行線程。只有一個任務可以同時運行,雖然在內部瀏覽器*可以*使用不同的線程簿記如定時器 – 2011-04-20 13:25:13

回答

2

可以使用實現這一Deferred jQuery中:

$.when(someTask1(), someTask2(), someTask3()).then(successFunc, errorFunc); 

你需要返回一個定製.Deferred對象與承諾值。

someTask2: function(someObj) 
{ 
    var def = $.Deferred(); 

    $.ajax({ 
      url: "someUrl.do", 
      type: "POST", 
      data: ({"id": rowObject.instanceId}), 
      dataType: "json", 
      async:false, 
      success: function(res){ 
       if(res.prop1 != 'desired'){ 
        setTimeout(function(){someTask2(someObj);}, 2000); 
       } 
       else 
       { 
       def.resolve(res); 
       } 
      } 
     } 
    ); 

    return def.promise(); 
} 

因此,例如:

function someTask1() 
{ 
    var def = $.Deferred(); 
    def.resolve('i\'m data resolved from task1'); 
    return def.promise(); 
} 

function someTask2(someObj) 
{ 
    var def = $.Deferred(); 

    var count = 0; 
    var f = function() { 
     console.log(++count); 
     if (count > 2) { 
      def.resolve('whoop we got the value we wanted in task 2 after many tries: ' + count); 
     } 
     else 
      setTimeout(f, 1000); 
    }; 
    f(); 
    return def.promise(); 
} 

function someTask3() 
{ 
    var def = $.Deferred(); 
    def.resolve('and hello from task3!'); 
    return def.promise(); 
} 

var success = function(x) { 
    console.log('success:', arguments); 
}; 

var error = function() { 
     console.log('oh no an error occured in one of the tasks.'); 
}; 

$.when(someTask1(), someTask2(), someTask3()).then(success , error); 

能顯示可用

1 
2 
3 
success: ["i'm data resolved from task1", 
      "whoop we got the value ...k 2 after many tries: 3", 
      "and hello from task3!"] 

小提琴:http://jsfiddle.net/garreh/29SW7/

+0

記住要改變你的任務,使他們像'yourObject.someTask2(someObj中)的跟蹤;' – 2011-04-20 12:39:37

+0

感謝答案是,我學到了一兩件事。但問題stays.' $。當(someTask2(someObj中),someTask3(someObj中)),然後(函數(){警報( '完成');});'功能仍然不叫秩序。可能是setTimeout創建問題。 – Nishant 2011-04-20 13:10:26

+0

+1用於引入非常酷的功能。更新了問題。 – Nishant 2011-04-20 13:16:28

1

你可以回調傳遞給someTask2。例如:

someTask2: function(someObj, callback){ 
$.ajax({ 
     url: "someUrl.do", 
     type: "POST", 
     data: ({"id": rowObject.instanceId}), 
     dataType: "json", 
     async:false, 
     success: function(res){ 
      if(res.prop1 != 'desired'){ 
       setTimeout(function(){someTask2(someObj, callback);}, 2000); 
      } else { 
      if (callback != null) { 
       callback(); 
      } 
      } 
     } 
    } 
); 
} 

然後,只需通過someTask3爲回調:

someTask2(someObj, function(){ someTask3(someObj); }); 
+0

是的,這將是最後的手段..我真的想避免它。更新的問題,順便說一句。 – Nishant 2011-04-20 13:17:15

+0

我不會害怕走這樣的方法。使用jQuery和Ajax工作時回調是一個很常見的模式,因爲往往你有你需要的異步操作後執行的功能。也就是說,如果您使用jQuery 1.5,Deferred可能是一個更好的選擇 - 尤其是一次(如果)您在應用程序的其他位置執行此操作。 – 2011-04-20 13:29:59

+0

絕對。 '.ajax'是一個延遲對象,如果不能利用它的強大功能,那將是愚蠢的。 – 2011-04-20 13:48:15

相關問題