顺序函数调用,而其中一个使用setTimeout

时间:2011-04-20 11:48:56

标签: javascript settimeout

我想按顺序调用三个函数someTask1someTask2someTask3。但是,函数someTask2涉及Ajax调用,并使用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内的代码按顺序执行。我怎么能这样做?

另外,我不想在someTask3回调中对success进行硬编码。例如。我不想这样做:

          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的调用会触发。

不确定我有多正确。

2 个答案:

答案 0 :(得分:2)

您可以使用jquery中的 Deferred 来实现此目的:

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

您需要返回一个带有promise值的自定义.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/

答案 1 :(得分: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); });