代码之家  ›  专栏  ›  技术社区  ›  Simsons

如何顺序或同步执行函数

  •  -1
  • Simsons  · 技术社区  · 6 年前

    我有4个函数,我想按顺序执行。

    尤其是第四个函数应该只在前面三个函数都完成时执行。

    我试着使用回拨,但肯定我没有正确地使用它。我如何使它有序。

    我听说了 then 函数,但看起来它只适用于 ECMAScript 6 (不确定),但当我尝试在脚本中使用它时,会得到一个未定义的错误。

    function longRunningFunction(callBack) {
    
      setTimeout(function() {
        $('#div1').html('Div1 Done');
      }, 5000);
      setTimeout(function() {
        $('#div2').html('Div2 Done');
      }, 5000);
      setTimeout(function() {
        $('#div3').html('Div3 Done');
      }, 5000);
    
      callBack();
    
    }
    longRunningFunction(function() {
      setTimeout(function() {
        $('#div4').html('But changes 1st!');
      }, 3000);
    });
    #div4 {
      font-weight: bold;
      color: red;
    }
    
    #div1 {
      margin-top: 20px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div id="div4">
      My content should be changes at last!
    </div>
    <div id="div1">
      Div1
    </div>
    <div id="div2">
      Div2
    </div>
    <div id="div3">
      Div3
    </div>
    4 回复  |  直到 6 年前
        1
  •  2
  •   Zenoo    6 年前

    你可以用 Promises 为了达到这个目的。
    Promise#all :

    Promise.all([p1, p2, p3]).then(() => {
      callBack();
    });
    

    function longRunningFunction(callBack) {
    
      let p1 = new Promise((resolve, reject) => {
        setTimeout(function() {
          $('#div1').html('Div1 Done');
          resolve();
        }, 5000);
      });
    
      let p2 = new Promise((resolve, reject) => {
        setTimeout(function() {
          $('#div2').html('Div2 Done');
          resolve();
        }, 5000);
      });
    
      let p3 = new Promise((resolve, reject) => {
        setTimeout(function() {
          $('#div3').html('Div3 Done');
          resolve();
        }, 5000);
      });
    
      Promise.all([p1, p2, p3]).then(() => {
        callBack();
      });
    }
    longRunningFunction(function() {
        $('#div4').html('But changes 1st!');
    });
    #div4 {
      font-weight: bold;
      color: red;
    }
    
    #div1 {
      margin-top: 20px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div id="div4">
      My content should be changes at last!
    </div>
    <div id="div1">
      Div1
    </div>
    <div id="div2">
      Div2
    </div>
    <div id="div3">
      Div3
    </div>
        2
  •  1
  •   Bartłomiej Gładys    6 年前

    您有关于setTimeout的x4函数,因此可以将简单函数与promise和async/await功能结合起来:

    只要替换一下 () => console.log() () => $('#div1').html('Div1 Done');

    function sequentialTimeout(time, func){
      return new Promise(resolve => setTimeout(() => resolve(func()), time));
    }
    
    async function sequence(){
      await sequentialTimeout(500, () => console.log('1'))
      await sequentialTimeout(500, () => console.log('2'))
      await sequentialTimeout(500, () => console.log('3'))
      sequentialTimeout(500, () => console.log('4'))
    }
    
    sequence()
        3
  •  1
  •   Robin Zigmond    6 年前

    你可以用承诺,正如另一个答案所说。但是,如果您认为对于这样一个简单的用例(可以说是这样的)来说,这是太多的“繁重的机器”,那么您可以为每个成功的超时设置一个标志,然后在所有超时都设置好之后触发回调。以下是一种方法:

    function longRunningFunction(callBack) {
    
      var done = [false, false, false];
    
      function checkIfDone(cb) {
        if (done[0] && done[1] && done[2]) {
          cb();
        }
      }
    
      setTimeout(function() {
        $('#div1').html('Div1 Done');
        done[0] = true;
        checkIfDone(callBack);
      }, 5000);
      setTimeout(function() {
        $('#div2').html('Div2 Done');
        done[1] = true;
        checkIfDone(callBack);
      }, 5000);
      setTimeout(function() {
        $('#div3').html('Div3 Done');
        done[2] = true;
        checkIfDone(callBack);
      }, 5000);
    }
    longRunningFunction(function() {
      setTimeout(function() {
        $('#div4').html('But changes 1st!');
      }, 3000);
    });
    
        4
  •  -3
  •   Marty    6 年前

    你可以试试发电机

    function* generateSequence() {
      yield 1;
      yield 2;
      return 3;
    }
    
    let generator = generateSequence();
    
    let one = generator.next();
    
    alert(JSON.stringify(one)); // {value: 1, done: false}