【问题标题】:JavaScript - returning from functionsJavaScript - 从函数返回
【发布时间】:2015-01-26 16:28:16
【问题描述】:

是否需要明确地从 JavaScript 函数返回?在其他语言中,当函数不返回时,我们往往会收到 堆栈溢出 错误,但 JavaScript 似乎并非如此。

此外,由于是异步的,有时很难确定函数何时返回。它们甚至在 AJAX 调用或 jQuery 动画完成之前就返回了。

例如,一个函数进行 AJAX 调用,并且在返回 AJAX 结果之前不应返回。问题是,AJAX 函数在单独的异步线程中运行。我们如何从这样的函数返回?

【问题讨论】:

    标签: javascript ajax asynchronous stack stack-overflow


    【解决方案1】:

    您似乎对 JS 的工作原理感到困惑:

    函数进行 AJAX 调用,并且在返回 AJAX 结果之前不应返回。麻烦的是,AJAX 函数运行在一个单独的异步线程中

    这句话包含几个谬误:

    1. 函数进行 AJAX 调用,并且在返回 AJAX 结果之前不应返回
    2. AJAX 函数在单独的异步线程中运行

    这两种说法都完全不真实,原因如下:

    进行 ajax 调用的函数就是这样做的:它发出一个调用,它发送一个请求。 AJAX 代表 Asynchronous JavaScript And XML,这是一个发出此类请求的函数,然后在请求发送后返回。请求会发生什么,以及在发回响应后如何处理它不是发出请求的函数的责任。考虑一下:

    function sendInfo(info)
    {
        var loader = $('#loader');
        $.ajax({
            url: 'your/url',
            data: info,
            type: 'post',
            success: function(response)
            {//this will get called when there is a response
                loader.hide();//access to outer scope!
            }
        });
        loader.show();
    }
    

    在这种情况下,$.ajax 是执行请求的函数。如果那是阻塞的,我们将无法显示加载程序。但是,该函数会在发送请求后返回,一旦有要处理的响应,就会调用success 回调。该函数将负责加载程序,即再次隐藏它。如果 AJAX 调用被阻止,我们就不会像今天几乎所有网站那样拥有响应式和动态的网站(自动完成谷歌搜索,甚至这个网站......)

    AJAX 函数在单独的线程中运行是不正确的。 AJAX 是一种请求,您所指的函数是发出请求的函数,它们不在单独的线程中运行,或者是回调/句柄。这些不在单独的线程中运行。
    JavaScript 一直是单线程的。它确实有一个事件循环。在每个事件上,JS 检查是否有绑定到处理该事件的侦听器。如果没有,那就结束,如果有,这些处理程序将一次调用一个。在调用这些处理程序时,不能执行其他代码。

    现在回答您的问题:我们如何从这些函数返回?好吧,在某种程度上,你已经是:所有函数都返回一些东西。但是我认为您想知道如何将这些函数的返回值分配给变量。简单的答案是:你不能。至少不是直接的:

    //not using jQuery:
    var returnVal = xhr.send();
    

    不会返回成功 (onreadystatechange) 处理程序的值,因为onreadystatechange 事件将发生 4 次!您可以做的是使用闭包变量、模块模式,或者,如果必须的话,使用全局变量。
    如果这些函数在单独的线程中运行,作用域和访问全局变量会给你留下很多并发问题,并且操作 DOM 将是正确的。相反,您可以这样做:

    var infoModule = (function()
    {
        var loader = $('#loader'),
            module = {response: undefined};
        module.sendInfo = function(info)
        {
            $.ajax({
                url: 'your/url',
                data: info,
                type: 'post',
                success: function(response)
                {//this will get called when there is a response
                    loader.hide();//access to outer scope!
                    module.response = response;
                }
            });
            loader.show();
        };
        return module;
    }());
    

    现在你可以这样做了:

    infoModule.sendInfo({data: 'foo'});
    

    请求完成后,您可以像这样得到调用的响应:

    infoModule.response;
    

    【讨论】:

      【解决方案2】:

      从 JavaScript 函数中明确返回不是必需的。

      The trouble is, the AJAX function runs in a separate asynchronous thread. How would we return from such a function?
      

      所有 JavaScript 函数都将在其作用域结束时返回。如果没有定义 return 语句,函数将返回 undefined。 AJAX 调用将返回到回调并在完成后引发readystatechange 事件。

      见:Does every Javascript function have to return a value?

      【讨论】:

      • 感谢您的回答,Gnuey。 1.那么,没有溢出的风险吗? 2.AJAX响应函数返回到哪里?生成它的函数会在 AJAX 调用后立即返回。
      • 据我所知,没有溢出的风险。我不太了解浏览器解释器等。正如您所说,可以编写进行 AJAX 调用并等待 AJAX 调用返回的函数。该函数称为“回调函数”。 AJAX 调用会将结果返回给此回调函数。在这里阅读更多:stackoverflow.com/questions/3523628/…
      • 一个 ajax 函数在单独的线程中运行。 JS 是单线程的。一旦readystatechange 事件触发,回调将被调用。此时,函数调用被放入调用队列中,以便尽快调用。但是函数本身与其余代码在同一个线程中调用,因此是阻塞的。编写一个需要几秒钟才能返回的回调/处理程序,您会注意到它阻塞了 UI。如果回调在单独的线程中运行,它就不能安全地访问更高的范围,并且访问 DOM 是有风险的,如果不是不可能的话
      • 感谢您的澄清!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-22
      • 2011-11-05
      相关资源
      最近更新 更多