如何强制顺序Javascript执行?

Tom*_*Tom 64 javascript asynchronous callback synchronous execution

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

<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>
Run Code Online (Sandbox Code Playgroud)

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

- -编辑 - -

所以这是一个垃圾的例子,但多亏了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>
Run Code Online (Sandbox Code Playgroud)

由于我的实际问题是jQuery和IE,我将不得不发布一个单独的问题,如果我自己无法到达任何地方!

Dav*_*und 46

好吧,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);
};
Run Code Online (Sandbox Code Playgroud)

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

  • 另外,我应该注意,AJAX请求通常是*异步的,但可以是同步的. (4认同)

Ray*_*ond 31

毕竟我回到这个问题因为我花了很长时间才找到我认为是一个干净的解决方案:强制我知道的javascript顺序执行的唯一方法是使用promises.承诺的详尽解释:Promises/APromises/A +

实现我知道的promises的唯一库是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>
Run Code Online (Sandbox Code Playgroud)

通过使用.then()实现一个promise和链接函数,你确保第二个函数只有在第一个函数执行后才会执行它是longfunctionfirst()中的命令d.resolve(),它给出了启动下一个函数的信号功能.

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

  • 那是一个美女 (4认同)
  • 大家好,我总是感到惊讶的是,这个旧的胎面仍然引起人们的注意.是的,你是对的,现在ES6和越来越多的框架实现了承诺.这是旧的东西,但它在5年前推动我上升,这是我在计算中学到的最难的一课.简单地说,我被困在Von Newmann对计算的顺序理解中,无法掌握Javascript所包含的事件驱动开发之美. (2认同)

Ray*_*ond 11

我是编程方面的老手,最近回到了我最近的热情,我正在努力适应这个面向对象,事件驱动的明亮的新世界,虽然我看到Javascript的非顺序行为的优势,但它有时间真正得到它在简单性和可重用性方面.我所做的一个简单例子就是拍照(用javascript,HTML,phonegap等编写的手机),调整大小并将其上传到网站上.理想的顺序是:

  1. 拍张照片
  2. 将照片加载到img元素中
  3. 调整图片大小(使用Pixastic)
  4. 将其上传到网站
  5. 告知用户成功失败

所有这些都是一个非常简单的顺序程序,如果我们将每个步骤在完成时将控制权返回到下一个程序,但实际上:

  1. 拍摄照片是异步的,因此程序会尝试在img元素存在之前加载它
  2. 加载照片是异步的,因此调整大小图片在img完全加载之前开始
  3. 调整大小是异步的,因此在完全调整图片大小之前,上传到网站
  4. 上传到网站是asyn所以程序在照片完全上传之前继续.

顺便说一下,5个步骤中的4个涉及回调函数.

因此我的解决方案是将每一步嵌套在前一步中并使用.onload和其他类似的策略,它看起来像这样:

takeAPhoto(takeaphotocallback(photo) {
  photo.onload = function () {
    resizePhoto(photo, resizePhotoCallback(photo) {
      uploadPhoto(photo, uploadPhotoCallback(status) {
        informUserOnOutcome();
      });
    }); 
  };
  loadPhoto(photo);
});
Run Code Online (Sandbox Code Playgroud)

(我希望我没有犯太多错误,把代码带到它上面,真正的东西太过分散了注意力)

这是一个完美的例子,其中异步不好并且同步是好的,因为与Ui事件处理相反,我们必须在执行下一步之前完成每一步,但代码是俄罗斯玩偶构造,它令人困惑且难以理解,代码的可重用性很难实现,因为所有的嵌套都很难将内部函数带到所需的所有参数,而无需依次将它们传递给每个容器或使用邪恶的全局变量,我会喜欢所有的结果这段代码会给我一个返回代码,但第一个容器将在返回代码可用之前完成.

现在回到Tom最初的问题,15年前使用简单的C和一个哑电子板,这将是一个非常简单的程序的智能,易读,易于重用的解决方案?

这个要求实际上是如此简单,以至于我的印象是我必须缺少对Javsascript和现代编程的基本理解,当然技术是为了提高生产力吗?

谢谢你的耐心

雷蒙德恐龙;-)

  • 我在phonegap遇到了同样的困难.我有一个充满嵌套回调函数的代码,很难读.在某些时候,我希望我原生地实现了应用程序.我正在研究录音机并将记录的数据与服务器同步.我尝试使用requirejs和backbone来简化我的代码.这有助于将事情分开并在模块中组织代码,但我仍然需要嵌套回调... (3认同)