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

sequential function call, while one of them uses setTimeout

本文关键字:一个 setTimeout 函数调用 顺序      更新时间:2023-09-26

我想按此顺序调用三个函数someTask1, someTask2someTask3。但是,函数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);
              }
          }
       }
    );
},

您可能已经猜到了,这段代码的执行在调用someTask3之前不会等待someTask2返回。

我希望doListOfTasks内的代码顺序执行。我该怎么做呢?

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

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

您可以在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/

您可以向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); });