【问题标题】:How to execute function sequentially or synchronously如何顺序或同步执行功能
【发布时间】:2018-09-13 16:27:07
【问题描述】:

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

特别是第 4 个函数应该只在前面的 3 个函数都完成时才执行。

我尝试使用回调,但可以肯定我没有正确使用它。如何使其连续。

我听说过 JavaScript 中的 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>

【问题讨论】:

  • 你想让Div2 Done在Div1 Done之后5000ms发生吗?
  • 把callback()放在最后一个setTimeout()的末尾。我还建议使用队列而不是超时,因为它可以为您提供更多可扩展的控制。
  • @CertainPerformance,不。我只想在所有 3 个函数完成后进行回调。
  • 您在尝试then 时遇到了什么错误? Promise 是您的方案的最佳解决方案,因此最好弄清楚您是否错误地使用它们,而不是想出一个不太可靠的替代方案。
  • @Simsons Promises 在所有当代浏览器中都原生支持。但它们不会神奇地出现,您需要显式创建一个 Promise(或调用一个这样做的函数)才能使用它的 .then() 方法。

标签: javascript jquery html promise


【解决方案1】:

您可以使用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>

【讨论】:

  • 超时只是 OP 用来尝试更好地确保所有 3 个在第 4 个之前完成的延迟。所以你可以在你的答案中删除那些。
  • 我们应该调用longRunningFunction而不是callBack吗? div4 没有变化!
  • @Simsons 我在Promise#all 通话中打错了字。现在已经修好了。
【解决方案2】:

你有关于 setTimeout 的 x4 函数,所以你可以结合简单的函数 whit promise 和 async/await 功能:

只需将() =&gt; console.log() 替换为() =&gt; $('#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()

【讨论】:

  • 不要传递回调。如果您绝对需要,只需使用then。您的方法也无法从 func() 调用中捕获错误。
  • @Bergi 我认为 1 深度回调是一个好方法。为什么你认为相反? 2. 为了简单起见,我没有添加拒绝。
  • 如果你使用await,根本不需要回调;如果你想使用一个,那么它应该是一个承诺then 回调。不,您不只是错过了reject(您会在哪里这样做,为什么在超时后?),您没有从func 捕获异常。使用 then 会自动执行此操作。
【解决方案3】:

正如另一个答案所说,您可以使用 Promises。但是,如果您认为对于这样一个简单的用例(可以说是这样)来说,这太过“繁重的机器”,您可以为每个成功的超时设置一个标志,然后在所有设置完成后触发回调。以下是一种方式:

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】:

    你可以试试生成器

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

    【讨论】:

    • 生成器(单独)无助于使异步代码顺序化。
    猜你喜欢
    • 1970-01-01
    • 2011-06-17
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    相关资源
    最近更新 更多