你如何让javascript代码按*顺序*执行

IT技术 javascript ajax order-of-execution
2021-02-25 08:51:25

好的,所以我很欣赏 Javascript 不是 C# 或 PHP,但我一直回到 Javascript 中的一个问题 - 不是 JS 本身,而是我对它的使用。

我有一个功能:

function updateStatuses(){

showLoader() //show the 'loader.gif' in the UI

updateStatus('cron1'); //performs an ajax request to get the status of something
updateStatus('cron2');
updateStatus('cron3');
updateStatus('cronEmail');
updateStatus('cronHourly');
updateStatus('cronDaily');

hideLoader(); //hide the 'loader.gif' in the UI

}

事实是,由于 Javascript 迫切希望在代码中跳转,加载器永远不会出现,因为 'hideLoader' 函数会在之后直接运行。

我怎样才能解决这个问题?或者换句话说,我怎样才能让一个 javascript 函数按照我在页面上写的顺序执行......

6个回答

出现问题是因为 AJAX 本质上是异步的。这意味着updateStatus()调用确实是按顺序执行的,但会立即返回,并且 JS 解释器会hideLoader()在从 AJAX 请求中检索任何数据之前到达

您应该hideLoader()在 AJAX 调用完成的事件上执行

确切地说,JS 在开始下一个作业之前不会等待 updateStatus 作业完成。如果 cron1 必须在 cron2 启动之前完成,等等。您需要将每个 updateStatus 设置为在上一次调用成功时运行。
2021-04-29 08:51:25

如果您在进行 AJAX 编程,您需要将 JavaScript 视为基于事件而不是过程。在执行第二个调用之前,您必须等到第一个调用完成。这样做的方法是将第二个调用绑定到第一个调用完成时触发的回调。在不了解 AJAX 库内部工作原理的情况下(希望您使用的是库),我无法告诉您如何执行此操作,但它可能看起来像这样:

showLoader();

  updateStatus('cron1', function() {
    updateStatus('cron2', function() {
      updateStatus('cron3', function() {
        updateStatus('cronEmail', function() {
          updateStatus('cronHourly', function() {
            updateStatus('cronDaily', funciton() { hideLoader(); })
          })
        })
      })
    })
  })
});

这个想法是,updateStatus采用它的正常参数,加上一个回调函数,在它完成时执行。传递一个函数以运行onComplete到提供此类钩子的函数是一种相当常见的模式

更新

如果你使用 jQuery,你可以在$.ajax()这里阅读http : //api.jquery.com/jQuery.ajax/

您的代码可能如下所示:

function updateStatus(arg) {
  // processing

  $.ajax({
     data : /* something */,
     url  : /* something */
  });

  // processing
}

您可以修改您的函数以将回调作为其第二个参数,如下所示:

function updateStatus(arg, onComplete) {
  $.ajax({
    data : /* something */,
    url  : /* something */,
    complete : onComplete // called when AJAX transaction finishes
  });

}

我认为您需要做的就是在代码中包含以下内容:

async: false,

所以你的 Ajax 调用看起来像这样:

jQuery.ajax({
            type: "GET",
            url: "something.html for example",
            dataType: "html",
            async: false,
            context: document.body,
            success: function(response){

                //do stuff here

            },
            error: function() {
                alert("Sorry, The requested property could not be found.");
            }  
        });

显然,一些这方面需要改变XMLJSON等等,但async: false,这里的要点,告诉JS引擎要等到成功的呼叫已恢复(或视失败)再进行。请记住,这样做有一个缺点,那就是整个页面都变得无响应,直到 ajax 返回!!!通常在几毫秒内,这不是什么大问题,但可能需要更长的时间。

希望这是正确的答案,它可以帮助您:)

虽然它有效,但这并不是一个很棒的答案。您希望 JS 是异步的。有许多优点和场景,您希望它做自己的事情,并且为您的整个应用程序将其全部关闭是不常见的。我建议改用Promise库。这是一个很棒的教程。Dailyjs.com/2014/02/20/promises-in-detail
2021-04-26 08:51:25
这个成功了。简单而简洁的解决方案。非常感谢。
2021-05-02 08:51:25

我们在我们的一个项目中有类似的东西,我们通过使用计数器解决了它。如果您updateStatus在 AJAX 请求的响应函数中增加每次调用的计数器并减少它(取决于您使用的 AJAX JavaScript 库。)

一旦计数器达到零,则所有 AJAX 请求都已完成,您可以调用hideLoader().

这是一个示例:

var loadCounter = 0;

function updateStatuses(){
    updateStatus('cron1'); //performs an ajax request to get the status of something
    updateStatus('cron2');
    updateStatus('cron3');    
    updateStatus('cronEmail');
    updateStatus('cronHourly');
    updateStatus('cronDaily');
}

function updateStatus(what) {
    loadCounter++;

    //perform your AJAX call and set the response method to updateStatusCompleted()
}

function updateStatusCompleted() {
    loadCounter--;
    if (loadCounter <= 0)
        hideLoader(); //hide the 'loader.gif' in the UI
}
嗨,Prutswonder,我刚试过这个,它有效!我喜欢这个解决方案
2021-04-19 08:51:25
+1 对于如此深度嵌套的一系列回调,可能比我的解决方案更好
2021-04-21 08:51:25
Ed,如果您喜欢这些解决方案之一,能否通过单击该人的答案旁边的复选框来标记您选择的最佳解决方案?
2021-04-24 08:51:25
您可能希望loadCounter < 0案例导致错误,因为如果发生这种情况,那就是错误。
2021-05-08 08:51:25

这与代码的执行顺序无关。

加载程序图像从未显示的原因是您的函数运行时 UI 不会更新。如果您在 UI 中进行了更改,则在您退出该功能并将控制权返回给浏览器之前,它们不会出现。

您可以在设置图像后使用超时,让浏览器有机会在开始其余代码之前更新 UI:

function updateStatuses(){

  showLoader() //show the 'loader.gif' in the UI

  // start a timeout that will start the rest of the code after the UI updates
  window.setTimeout(function(){
    updateStatus('cron1'); //performs an ajax request to get the status of something
    updateStatus('cron2');
    updateStatus('cron3');
    updateStatus('cronEmail');
    updateStatus('cronHourly');
    updateStatus('cronDaily');

    hideLoader(); //hide the 'loader.gif' in the UI
  },0);
}

还有另一个因素也可以使您的代码看起来乱序执行。如果您的 AJAX 请求是异步的,则该函数不会等待响应。处理响应的函数将在浏览器接收到响应时运行。如果您想在收到响应后隐藏加载程序图像,则必须在最后一个响应处理程序函数运行时执行此操作。由于响应不必按照您发送请求的顺序到达,因此您需要计算在最后一个响应到来时您知道多少响应。

多亏了 Guffa 和 Sbaitso 博士,我对引擎盖下发生的事情有了更多的了解,我将尝试一下您的一些建议,看看我能做些什么!
2021-04-25 08:51:25