jQuery:ajax调用成功后返回数据

IT技术 javascript jquery ajax
2021-01-31 22:37:42

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

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; 
}
5个回答

注意:此答案写于 2010 年 2 月。
请参阅底部的 2015、2016 和 2017 年更新。

您不能从异步函数返回任何内容。你能回报的是一个Promise我在回答这些问题时解释了 jQuery 中的 Promise 是如何工作的:

如果您可以解释为什么要返回数据以及稍后您想用它做什么,那么我可能会给您一个更具体的答案如何去做。

通常,而不是:

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

您可以像这样编写 testAjax 函数:

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

然后你可以像这样得到你的Promise:

var promise = testAjax();

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

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

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

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

执行所有这些操作的全部意义在于,您的数据在调用 $.ajax 后不会立即可用,因为它是异步的。Promises 是函数的一个很好的抽象,可以说:我无法返回数据,因为我还没有它,而且我不想阻塞并让你等待,所以这里是一个Promise,你将能够稍后使用它,或者只是将它交给其他人并完成它。

看到这个演示

更新 (2015)

目前(截至 2015 年 3 月)jQuery Promises 与Promises/A+ 规范不兼容,这意味着它们可能无法与其他Promises/A+ 一致性实现很好地合作

然而,即将发布的 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 等人的来自 jQuery在 Q 库 wiki 上,Promises在 HTML5 Rocks 上由 Jake Archibald在 JavaScript 中实现

如何返回一个真正的Promise

我上面例子中的函数:

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

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

为了使它返回一个真正的Promise,您可以将其更改为 - 使用Q wiki 中的方法

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

或者,使用HTML5 Rocks 文章中的方法

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

Promise.resolve($.ajax(...))也是module文档中解释的promise内容,它应该适用于ES6Promise.resolve()

今天要使用 ES6 Promises,您可以使用Jake Archibald 的es6-promise modulepolyfill()

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

有关更多信息,请参阅:

jQuery 的未来

jQuery 的未来版本(从 3.x 开始 - 截至 2015 年 5 月的当前稳定版本是 1.x 和 2.x)将与Promises/A+ 规范兼容(感谢Benjamin Gruenbaum在评论中指出)。“我们已经决定的两个变化是我们的延迟实现的 Promise/A+ 兼容性 [...]”jQuery 3.0 和 Web 开发的未来)。有关更多信息,请参阅:jQuery 3.0: Dave Methvin 的下一代jQuery 3.0: Paul Krill 的更多互操作性,更少的 Internet Explorer

有趣的谈话

更新 (2016)

ECMA-262,第 6 版,第 14.2 节中有一种称为箭头函数的新语法,可用于进一步简化上述示例。

使用 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的拒绝处理程序:

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

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

并非每个浏览器都支持这种语法,但在某些情况下,您可以确定代码将在哪个浏览器上运行 - 例如,在编写Chrome 扩展程序Firefox 插件或使用 Electron、NW.js 或AppJS(有关详细信息,请参阅此答案)。

有关箭头函数的支持,请参阅:

更新 (2017)

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

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:

或者使用稍微不同的语法基于生成器的方法,例如 inco或 Bluebird 协程:

更多信息

有关 promise 的其他一些问题以获取更多详细信息:

@rsp 确实很好的答案!但是我已经按照您的演示代码进行了操作,它似乎调用了 ajax 两次(有没有其他人注意到相同的情况?)。
2021-03-12 22:37:42
@AlexG 在promise.success(function (data) { alert(data); });我的示例中,您可以使用promise.success(function (data) { alert(data.users[0].id); alert(data.prices[x]); });或类似的东西。如果您在success回调(或then回调,如果您使用 Promises/A+ API)中获得数据,那么您将获得数据及其所有属性。
2021-03-20 22:37:42
他们只是在玩弄 ajax,看看它是如何工作的。
2021-03-21 22:37:42
完美的答案!只是为用户添加一个旁注,这不适用于 jQuery 1.4 版。
2021-03-22 22:37:42
这有很大帮助。我只是跳过了步骤var promise = testAjax()并做到了这一点 testAjax().success(function (data) { alert(data); });
2021-03-25 22:37:42

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

您可以传入处理结果的回调函数:

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.
@Mike:问题是除非您有 TARDIS,否则您无法从通话中获得结果。由于调用是异步的,所以调用返回后才会有结果。您可以考虑使用此处其他答案中提供的Promise,即使结果尚未到达,您也可以从调用中返回一些内容。在某些时候,无论如何你都必须等待结果,promise 只是让你在代码的不同部分这样做。
2021-03-12 22:37:42
@iamsirjayesh 我会为你做数学,只有 5.5 年!...然而有帮助的答案。
2021-03-29 22:37:42
success并且error在 jQuery 1.8 中被弃用。你应该开始使用.done().fail()请参阅文档
2021-03-30 22:37:42
不推荐使用的是回调操作函数(例如 .error、.success)而不是 ajax 方法的参数。请参阅此线程中的评论。 stackoverflow.com/a/10931891/4490454
2021-03-30 22:37:42
我想添加 [success] 状态会延迟一些并且更准确地只在状态为 400 成功时调用。
2021-04-02 22:37:42

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

function testAjax() {
    var result="";
    $.ajax({
      url:"getvalue.php",
      async: false,  
      success:function(data) {
         result = data; 
      }
   });
   return result;
}
async: false对于大多数用例whatwg 规范现在已弃用当调用async: false. w3c 规范似乎还没有弃用它。
2021-03-10 22:37:42
你的解决方案是完全有效的。我只想强调不要在成功回调中立即返回值,而是在 .ajax 函数调用之外返回值的重要性。否则你会得到未定义。
2021-03-14 22:37:42
这对我来说没有用……结果在我的 return 语句中未定义!
2021-03-20 22:37:42
有没有办法将这个函数与 async:true 一起使用?
2021-03-29 22:37:42
为什么这不起作用?function get_cmd_info3(cmd){ var result = null; $.get("bash/"+cmd, function(data) { console.log(data); result = data }, 'json'); 返回结果;}
2021-04-02 22:37:42

Idk 如果你们解决了它,但我推荐另一种方法来做到这一点,它的工作原理:)

    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,然后你让一切都等待,直到数据被检索。然后你将它分配给类的一个静态变量,一切都神奇地工作:)

这已在此答案中提出(stackoverflow.com/a/7891780/218196)。通常,发出同步 Ajax 请求不是一个好主意。
2021-03-17 22:37:42

请参阅 jquery 文档示例:http : //api.jquery.com/jQuery.ajax/ (大约页面的 2/3)

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

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

同一页……往下。

否 如果在另一个函数内部进一步处理需要结果怎么办?,您将如何将其传递到那里?
2021-03-16 22:37:42