【问题标题】:Why can't / shouldn't I use a while loop to monitor asynchronous jQuery operations?为什么我不能/不应该使用 while 循环来监控异步 jQuery 操作?
【发布时间】:2012-07-13 17:01:06
【问题描述】:

我正试图集中精力协调异步操作。我需要一点帮助理解:

  1. 为什么使用 while 循环来等待操作完成是一个坏主意并且不起作用,并且
  2. 如果有在 jQuery 函数上使用回调的可行替代方法

大多数情况下,将回调添加到像 $.get() 这样的异步函数效果很好。然而,在某种程度上,这确实决定了我不喜欢的代码的编写方式和位置。

$(function() {

    var r = AjaxResults( page );

    // loop prevents further processing until GetResults() is done
    while( isComplete == false )
    isComplete = $('body').data('isComplete');

    // reset isComplete boolean
    $('body').data('isComplete', false);

    // this will only continue after GetResults() has exited
    paintTheTownRed();
    var whateverElse = true;
});

function AjaxResults( page ) {

   // do something before async operation
   switch( page ){
       case '1': {...} break;
       ...
       default: break;
   } 

   $.getJSON("/controller/page", null, function(data) {

       // do something after async operation
       {...}

       $('body').data('isComplete', true);
       return data;
   });
}

【问题讨论】:

  • 我不明白你的问题。回调是编程的标准部分。 “规定了我不喜欢的代码的编写方式和位置”是什么意思?
  • @scott.korin 我相信他的意思是它通常要求程序员要么到处传递回调处理程序,和/或过度嵌套匿名函数。 $.Deferred 是这两个问题的答案。

标签: javascript jquery ajax asynchronous coordinate


【解决方案1】:

因为它会占用我的 CPU 并极大地刺激我。

在哪里编写代码几乎从不由 asynch/synch 决定;函数是函数,无论它们是匿名的并内联编写,还是命名并作为引用传递。

此外,promise 和 deferred objects 有助于决定在何处/如何实现功能。

请参阅.when (docs) 之类的内容了解更多详细信息和想法,但还有其他使用方式。

【讨论】:

    【解决方案2】:

    简而言之,您不应该这样做,因为这将是非常糟糕的用户体验,并且会严重激怒大多数/所有观众。充其量它会刺激 CPU 并不必要地耗尽观众的电池。在最坏的情况下,观看者会认为他们的浏览器死机/挂起。

    因为 javascript 是单线程的,并且单线程与浏览器中的用户事件处理相关联,如果您使用 while 循环循环等待异步事件完成,您将在执行期间锁定浏览器while 循环。您可能还会发现,一些浏览器会给用户一个警告,提示 JavaScript 运行时间过长。

    目前没有替代某种类型的回调用于 javascript 中的异步编程。如果您想使用异步操作,那么您必须使您的编程风格适应它们的工作方式,以保持良好的用户体验。是的,这意味着调整你的编程风格,但这是为了保持良好的用户体验而付出的代价。 Deferred objects 可以为您提供一种更令人愉悦的代码编写方式(它仍然是回调,但似乎少了一些)如果您想对此进行调查。

    按照您的建议,您的编程便利性优先于用户体验,这只是一个糟糕/懒惰的程序员的标志,他们的目标/优先级似乎倒退了。

    仅供参考,即使在允许并且可以工作的环境(如原生 Windows 开发)中,这也是一种糟糕的编程习惯。

    【讨论】:

    • 谢谢。对我来说,这是问题的核心:Because javascript is single threaded and that single threadedness is tied to the user event handling in the browser
    【解决方案3】:

    大多数情况下,将回调添加到像 $.get() 这样的异步函数效果很好。然而,在某种程度上,这确实决定了我不喜欢我的代码的编写方式和位置。

    不再需要直接向 AJAX 函数添加回调。

    使用 jQuery deferred objects 让您在不需要过多嵌套的情况下编写代码:

    function AjaxResults( page ) {
        ...  // prep
        return $.getJSON("/controller/page", null)
            .done(function(data) {
                // always do this
            });
    }
    
    AjaxResults(page).done(paintTheTownRed);
    

    请务必将您自己的complete 处理程序放在$.getJSON 上,如此处所示,但是通过返回 jqXHR 对象,您有机会做额外无需传递大量回调或嵌套代码。

    【讨论】:

    • @DaveNewton 是的,它们是我最喜欢的 jQuery 功能之一!
    【解决方案4】:

    如果您的问题是您不喜欢定义在 $.get() 中调用的函数,那么请务必将其写为单独的函数:

    $(function() {
    
        AjaxResults( page );
    
    });
    
    function AjaxResults( page ) {
    
       // do something before async operation
       switch( page ){
           case '1': {...} break;
           ...
           default: break;
       } 
    
       $.getJSON("/controller/page", null, doWhatever);
    }
    
    function doWhatever(data) {
        paintTheTownRed();
        var whateverElse = true;
    }
    

    【讨论】:

    • 不,这是不好的做法——它将doWhateverAjaxResults 函数联系在一起。它可以作为参数传递,但$.Deferred 更好。
    • 在这个特定的例子中,与将处理程序传递给函数 AJaxResults( page, fn) 相比,使用委托能给您带来什么?总的来说,我了解委托的用途,但我不明白为什么它是必要的,或者它实际上如何改变他的结构中的任何内容。
    • 使用$.Deferred 让您可以灵活地绑定任意数量的处理程序,并公开$.getJSON 不支持的错误处理功能。
    【解决方案5】:

    嗯,这是个坏主意,因为它不起作用。回调函数 永远不会被调用,因为您处于 while 循环中,因此布尔值不会更改为 true,因此它是一个无限循环

    现在,为什么实际的同步请求是一个坏主意,因为它们冻结了 UI 并让我认为选项卡崩溃了。但是,是的,同步请求是回调的替代方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-27
      • 2019-05-10
      • 2015-07-01
      • 1970-01-01
      • 2018-02-18
      • 2011-11-12
      • 2018-05-23
      • 2022-12-12
      相关资源
      最近更新 更多