如何强制Sequential Javascript执行?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (9)

我只找到相当复杂的答案,涉及类,事件处理程序和回调(在我看来,这是一种有点大锤的方法)。我认为回调可能有用,但我似乎无法在最简单的情况下应用这些回调。看到这个例子:

<html>
  <head>
    <script type="text/javascript">
      function myfunction()  {
        longfunctionfirst();
        shortfunctionsecond();
      }

      function longfunctionfirst() {
        setTimeout('alert("first function finished");',3000);
      }

      function shortfunctionsecond() {
        setTimeout('alert("second function finished");',200);
      }
    </script>
  </head>
  <body>
    <a href="#" onclick="javascript:myfunction();return false;">Call my function</a>
  </body>
</html>

在此,第二个函数在第一个函数之前完成; 什么是最简单的方法(或者是否存在?)来强制第二个函数延迟执行直到第一个函数完成?

- -编辑 - -

所以这是一个垃圾的例子,但感谢David Hedlund,我用这个新例子看到它确实是同步的(伴随着测试过程中我的浏览器崩溃!):

<html>
<head>

<script type="text/javascript">
function myfunction() {
    longfunctionfirst();
    shortfunctionsecond();
}

function longfunctionfirst() {
    var j = 10000;
    for (var i=0; i<j; i++) {
        document.body.innerHTML += i;
    }
    alert("first function finished");
}

function shortfunctionsecond() {
    var j = 10;
    for (var i=0; i<j; i++) {
        document.body.innerHTML += i;
    }
    alert("second function finished");
}
</script>

</head>

<body>
  <a href="#" onclick="javascript:myfunction();return false;">Call my function</a>
</body>
</html>

由于我的实际问题是使用jQuery和IE,我将不得不单独发布一个关于如果我自己无法获取的问题!

提问于
用户回答回答于

那么,setTimeout根据它的定义,它不会妨碍这个线程。这是可取的,因为如果它这样做,它会冻结整个UI等待的时间。如果你真的需要使用setTimeout,那么你应该使用回调函数:

function myfunction() {
    longfunctionfirst(shortfunctionsecond);
}

function longfunctionfirst(callback) {
    setTimeout(function() {
        alert('first function finished');
        if(typeof callback == 'function')
            callback();
    }, 3000);
};

function shortfunctionsecond() {
    setTimeout('alert("second function finished");', 200);
};

如果你不使用setTimeout,但只具有执行很长的功能,并使用setTimeout来模拟,那么你的功能会实际上是同步的,你不会有这个问题的。但是,应该指出的是,AJAX请求是异步的,并且只会setTimeout在UI线程完成之前阻止它。与AJAX一样setTimeout,您必须使用回调。

用户回答回答于

我经常回到这个问题,因为我花了很长时间才发现我认为是一个干净的解决方案:我知道强制执行javascript顺序执行的唯一方法就是使用promise。Promise / APromises / A +的承诺详尽阐述

唯一实现承诺的库是jquery,所以这里是我将如何使用jquery promise来解决问题:

<html>
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script type="text/javascript">
    function myfunction()
    {
        promise = longfunctionfirst().then(shortfunctionsecond);
    }
    function longfunctionfirst()
    {
        d = new $.Deferred();
        setTimeout('alert("first function finished");d.resolve()',3000);
        return d.promise()
    }
    function shortfunctionsecond()
    {
        d = new $.Deferred();
        setTimeout('alert("second function finished");d.resolve()',200);
        return d.promise()
    }
    </script>
</head>
<body>
    <a href="#" onclick="javascript:myfunction();return false;">Call my function</a>
</body>
</html>

通过实现一个承诺并用.then()函数链接函数,可以确保第二个函数仅在第一个函数执行后才会被执行。它是longfunctionfirst()中的命令d.resolve(),它使信号开始下一个功能。

从技术上讲,shortfunctionsecond()不需要创建一个延期并返回一个承诺,但我爱上了承诺并倾向于用承诺实现一切,对不起。

扫码关注云+社区