【问题标题】:jQuery: Return data after ajax call success [duplicate]jQuery:ajax调用成功后返回数据[重复]
【发布时间】:2011-07-16 01:26:03
【问题描述】:

我有这样的东西,它是一个简单的脚本调用,它给我一个值,一个字符串..

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {
         return data; 
      }
   });
}

但如果我这样称呼

var output = testAjax(svar);  // output will be undefined...

那么我怎样才能返回值呢? 下面的代码似乎也不起作用......

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {

      }
   });
   return data; 
}

【问题讨论】:

标签: javascript jquery ajax


【解决方案1】:

注意:此答案写于 2010 年 2 月。
在底部查看 2015、2016 和 2017 年的更新。

您不能从异步函数返回任何内容。您可以返回的是一个承诺。我在对这些问题的回答中解释了 promise 在 jQuery 中的工作原理:

如果你能解释为什么你想返回数据以及你想在以后做什么,那么我可能会给你一个更具体的答案。

通常,而不是:

function testAjax() {
  $.ajax({
    url: "getvalue.php",  
    success: function(data) {
      return data; 
    }
  });
}

你可以像这样编写你的 testAjax 函数:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

那么你可以像这样得到你的承诺:

var promise = testAjax();

你可以存储你的承诺,你可以传递它,你可以在函数调用中将它用作参数,你可以从函数中返回它,但是当你最终想要使用你的数据时由 AJAX 调用返回,你必须这样做:

promise.success(function (data) {
  alert(data);
});

(有关简化语法,请参阅下面的更新。)

如果此时您的数据可用,则将立即调用此函数。如果不是,则在数据可用时立即调用它。

执行所有这些操作的重点在于,您的数据在调用 $.ajax 后无法立即使用,因为它是异步的。 Promises 是函数的一个很好的抽象:我无法返回数据,因为我还没有数据,我不想阻止并让你等待,所以这里有一个 promise并且您以后可以使用它,或者只是将它交给其他人并使用它。

看到这个DEMO

更新(2015 年)

目前(截至 2015 年 3 月)jQuery Promises 与 Promises/A+ specification 不兼容,这意味着它们可能无法与其他 Promises/A+ conformant implementations 很好地合作。

不过,即将发布的 3.x 版本中的 jQuery Promises 与 Promises/A+ 规范兼容(感谢Benjamin Gruenbaum 的指出)。目前(截至 2015 年 5 月)jQuery 的稳定版本是 1.x 和 2.x。

我在上面(2011 年 3 月)解释的是一种使用 jQuery Deferred Objects 异步执行某些操作的方法,在同步代码中将通过返回一个值来实现。

但是同步函数调用可以做两件事——它可以返回一个值(如果可以的话)或者抛出一个异常(如果它不能返回一个值)。 Promises/A+ 以与同步代码中的异常处理一样强大的方式解决了这两个用例。 jQuery 版本处理等价的返回值就好了,但等价的复杂异常处理有点问题。

特别是,同步代码中异常处理的全部意义不仅仅是放弃一条好消息,而是尝试解决问题并继续执行,或者可能为代码的其他部分重新抛出相同或不同的异常要处理的程序。在同步代码中,您有一个调用堆栈。在异步调用中,您不需要按照 Promises/A+ 规范的要求在您的 Promise 中进行高级异常处理,这可以真正帮助您编写代码,以一种有意义的方式处理错误和异常,即使对于复杂的用例也是如此。

关于 jQuery 和其他实现之间的差异,以及如何将 jQuery Promise 转换为符合 Promises/A+ 标准,请参阅 Kris Kowal 等人的 Coming from jQuery。在 Q library wiki 上,Promises arrive in JavaScript by Jake Archibald 在 HTML5 Rocks 上。

如何兑现真正的承诺

我上面例子中的函数:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

返回一个 jqXHR 对象,它是一个 jQuery Deferred Object

要让它返回一个真正的承诺,您可以将其更改为 - 使用 the method from the Q wiki:

function testAjax() {
  return Q($.ajax({
      url: "getvalue.php"
  }));
}

或者,使用the method from the HTML5 Rocks article

function testAjax() {
  return Promise.resolve($.ajax({
      url: "getvalue.php"
  }));
}

这个Promise.resolve($.ajax(...)) 也是explained in the promise module documentation,它应该与ES6 Promise.resolve() 一起使用。

今天要使用 ES6 Promises,您可以使用 Jake Archibald 的 es6-promise module's polyfill()

要查看在没有 polyfill 的情况下可以在哪里使用 ES6 Promises,请参阅:Can I use: Promises

更多信息见:

jQuery 的未来

jQuery 的未来版本(从 3.x 开始 - 截至 2015 年 5 月的当前稳定版本是 1.x 和 2.x)将与 Promises/A+ specification 兼容(感谢 Benjamin Gruenbaum 在厘米)。 “我们已经决定的两个更改是我们的 Deferred 实现的 Promise/A+ 兼容性 [...]” (jQuery 3.0 and the future of Web development)。有关详细信息,请参阅:Dave Methvin 的 jQuery 3.0: The Next Generations 和 Paul Krill 的 jQuery 3.0: More interoperability, less Internet Explorer

有趣的谈话

更新(2016 年)

ECMA-262, 6th Edition, Section 14.2 中有一个名为arrow functions 的新语法,可用于进一步简化上述示例。

使用 jQuery API,而不是:

promise.success(function (data) {
  alert(data);
});

你可以写:

promise.success(data => alert(data));

或使用 Promises/A+ API:

promise.then(data => alert(data));

请记住始终使用拒绝处理程序:

promise.then(data => alert(data), error => alert(error));

或与:

promise.then(data => alert(data)).catch(error => alert(error));

查看这个答案,了解为什么您应该始终使用带有承诺的拒绝处理程序:

当然,在本例中,您可以只使用 promise.then(alert),因为您只是使用与回调相同的参数调用 alert,但箭头语法更通用,您可以编写如下内容:

promise.then(data => alert("x is " + data.x));

并不是每个浏览器都支持这种语法,但在某些情况下,您可以确定您的代码将在哪个浏览器上运行 - 例如。在使用 Electron、NW.js 或 AppJS 编写 Chrome extensionFirefox Add-on 或桌面应用程序时(详见 this answer)。

箭头函数的支持见:

更新(2017 年)

现在有一种更新的语法称为异步函数,它带有一个新的 await 关键字,而不是以下代码:

functionReturningPromise()
    .then(data => console.log('Data:', data))
    .catch(error => console.log('Error:', error));

让你写:

try {
    let data = await functionReturningPromise();
    console.log('Data:', data);
} catch (error) {
    console.log('Error:', error);
}

您只能在使用 async 关键字创建的函数内部使用它。有关详细信息,请参阅:

有关浏览器的支持,请参阅:

有关 Node 中的支持,请参阅:

在你没有原生支持 asyncawait 的地方你可以使用 Babel:

或者在语法稍有不同的情况下使用基于生成器的方法,例如 co 或 Bluebird 协程:

更多信息

关于更多细节的一些其他问题:

【讨论】:

  • 他们只是在玩弄 ajax,看看它是如何工作的。
  • 完美答案!只是为用户添加一个旁注,这不适用于 jQuery 版本 1.4。
  • 这很有帮助。我只是跳过了步骤var promise = testAjax() 并做了这个testAjax().success(function (data) { alert(data); });
  • @rsp 确实是很棒的答案!但是我已经按照你的演示代码,它似乎调用了两次 ajax(其他人注意到了吗?)。
  • @AlexG 在我的示例中,您可以使用promise.success(function (data) { alert(data.users[0].id); alert(data.prices[x]); }); 或类似的东西来代替promise.success(function (data) { alert(data); });。如果您在 success 回调(或 then 回调,如果您使用 Promises/A+ API)中获取数据,那么您将获得具有所有属性的数据。
【解决方案2】:

从函数返回数据的唯一方法是进行同步调用而不是异步调用,但这会在等待响应时冻结浏览器。

你可以传入一个处理结果的回调函数:

function testAjax(handleData) {
  $.ajax({
    url:"getvalue.php",  
    success:function(data) {
      handleData(data); 
    }
  });
}

这样称呼它:

testAjax(function(output){
  // here you use the output
});
// Note: the call won't wait for the result,
// so it will continue with the code here while waiting.

【讨论】:

  • 我猜添加 [success] 状态会延迟一些,更准确的是仅在状态为 400 成功时调用。
  • @iamsirjayesh 我会为你做数学,只有 5.5 年! ...但是有帮助的答案。
  • successerror 在 jQuery 1.8 中被弃用。您应该开始使用.done().fail()。见the documentation
  • 不推荐使用的是回调操作函数(例如 .error、.success)而不是 ajax 方法的参数。请参阅此线程中的 cmets。 stackoverflow.com/a/10931891/4490454
  • @Mike:问题是除非你有 TARDIS,否则你无法从调用中得到结果。由于调用是异步的,结果会在调用返回后到达。您可以在此处查看使用其他答案中提供的承诺,即使结果尚未到达,您也可以从调用中返回一些内容。无论如何,在某些时候你必须等待结果,promise 只是让你在代码的不同部分做到这一点。
【解决方案3】:

您可以将异步选项添加到 false 在 ajax 调用之外返回。

function testAjax() {
    var result="";
    $.ajax({
      url:"getvalue.php",
      async: false,  
      success:function(data) {
         result = data; 
      }
   });
   return result;
}

【讨论】:

  • 您的解决方案完全有效。我只是想强调在成功回调内部而不是在 .ajax 函数调用之外立即返回值的重要性。否则你会得到未定义的。
  • 有什么方法可以将此函数与 async:true 一起使用?
  • 对于大多数用例,async: false 现在在 whatwg spec 中已弃用。当与async: false 发生呼叫时,谷歌浏览器已经在其控制台中发出警告。 w3c spec 似乎还没有弃用它。
  • 为什么这不起作用?函数 get_cmd_info3(cmd){ var 结果 = null; $.get("bash/"+cmd, function(data) { console.log(data); result = data }, 'json');返回结果; }
  • 这对我来说没有用。结果在我的返回声明中是未定义的!
【解决方案4】:

如果你们解决了,我想知道,但我推荐另一种方法,它有效:)

    ServiceUtil = ig.Class.extend({
        base_url : 'someurl',

        sendRequest: function(request)
        {
            var url = this.base_url + request;
            var requestVar = new XMLHttpRequest();
            dataGet = false;

            $.ajax({
                url: url,
                async: false,
                type: "get",
                success: function(data){
                    ServiceUtil.objDataReturned = data;
                }
            });
            return ServiceUtil.objDataReturned;                
        }
    })

所以这里的主要思想是,通过添加 async: false,您可以让一切都等待,直到检索到数据。然后你把它分配给类的一个静态变量,一切都会神奇地工作:)

【讨论】:

【解决方案5】:

查看 jquery 文档示例: http://api.jquery.com/jQuery.ajax/ (大约 2/3 页)

您可能正在寻找以下代码:

    $.ajax({
     url: 'ajax/test.html',
     success: function(data) {
     $('.result').html(data);
     alert('Load was performed.');
   }
});

同一页...向下。

【讨论】:

  • NO 如果在另一个函数内部进一步处理需要结果怎么办?,你将如何将它传递到那里?
猜你喜欢
  • 2014-03-21
  • 2015-04-19
  • 1970-01-01
  • 1970-01-01
  • 2017-12-15
  • 1970-01-01
  • 2016-07-28
  • 2020-07-02
相关资源
最近更新 更多