jQuery.ajax()成功回调函数存储数据以返回

3

我正在尝试从一个PHP脚本中获取一些数据。我发现的所有使用AJAX回调函数的例子都在回调本身中使用数据,但是我想获取数据并以准备好返回的方式存储它。

function getEle (id) {
    var element = []; 

    $.ajax({
        url: 'slides.php',
        type: 'POST',
        data: {"id": id},
        success: function(data) {
            var content = data;

            element[0] = id;
            element[1] = content;
            // if I alert(element[1]); here it will work! 



        }
    });
    alert(element[1]); // here it just won't :/ ("undefined")
    return element;
}

在我的脚本中,某个函数需要 getEle(ments),但是我收到的只是 undefined。 有没有办法实现我想要的功能?或者也许有更好的方法来解决这个问题吗?


3
欢迎来到异步编程的精彩世界!你不能这样做。 - SLaks
5个回答

7
一种解决方案是将回调函数传递给getEle()函数:
getEle(id, callback){
  $.ajax({
    /* some options, */
    success: function(){
      var content = data;
      element[0] = id;
      element[1] = content;
      callback(element);
    }
  })
}

然后传递一个包含代码的函数,用于在具有元素内容时执行该代码:

getEle('myId', function(element){
  alert(element[1]);
});

我四年后又来到这里,看到自己的问题不禁笑了一下。 :) 你的答案似乎比我当初接受的更合适,尽管现在我可能会使用 promises 或 async/await。干杯! - Otze
哈哈,很高兴看到你仍在走着异步问题的路。我也在继续走着它。 :) - Avaq

2
这里有两个问题:
  • 变量作用域 - 你在 AJAX 回调函数内定义了变量 content,这使得它无法从周围的代码中访问。你可以省略 var 直接写 content = data,这样就可以全局访问。
  • 异步性 - 因为 AJAX 是异步的,所以在回调函数之后执行的脚本将在回调函数之前执行。解决这个问题的唯一方法是按照其设计意图使用回调函数。

看一下这个例子。

function getEle (id, callback) {
        var element = []; 

        $.ajax({
            url: 'slides.php',
            type: 'POST',
            data: {"id": id},
            success: function(data) {
                var content = data;
                element[0] = id;
                element[1] = content;

                callback(element);
            }
        });
    }
}

getEle ("someID", function(someElement) {
    alert(someElement);
});

1

以下是您代码中正在发生的事情:

  • 数组“element”已初始化。
  • 使用成功回调函数进行AJAX调用
  • 在等待AJAX运行时,它继续执行其余代码并警告element [1],但该元素尚不存在
  • 成功回调运行并填充数组“element”。

您可以考虑使用全局变量来解决此问题:

var element = []; 

function getEle (id) {
    $.ajax({
        url: 'slides.php',
        type: 'POST',
        data: {"id": id},
        success: function(data) {
            var content = data;
            element[0] = id;      // the global "element" is set
            element[1] = content;
        }
    });
}
// element[0] will exist now, but only after the AJAX call is complete

或者,您可以将您的 AJAX 转换为同步调用:

function getEle (id) {
    var element = []; 

    $.ajax({
        async: false,   // forces synchronous call
        url: 'slides.php',
        type: 'POST',
        data: {"id": id},
        success: function(data) {
            var content = data;
            element[0] = id;
            element[1] = content;
        }
    });
    alert(element[1]); // now it is set
    return element;
}

我能看到的其他选项是保持所有内容都在“成功”回调函数中,你已经发现它可以正常工作。

2
你的问题一开始很好,直到你提到这个全局变量。我取消了我的点赞。全局变量是无用的,因为你不知道何时该变量可以使用。唯一知道它何时可以使用的地方是在成功回调函数内部,因此你根本不需要全局变量。至于 async: false,我更喜欢不加评论。 - Darin Dimitrov
好的,但现在你搞砸了我的整个想法 ;) - Otze
@DarinDimitrov OP已经知道element在“success”回调函数中被设置了;我认为这不需要重复。至于全局变量,它们经常被误用,但绝不是无用的。如果那些数据需要在触发某些用户事件后重新访问,为什么不将其全局存储呢? - Blazemonger
@mblase75,因为你无法保证这些数据可用。正如我所说,唯一可以保证数据可用的事件/位置是在AJAX成功回调函数内部。 - Darin Dimitrov
@DarinDimitrov 保证并非总是必要的。例如:使用 AJAX 从数据库中获取多行数据。将所有行作为数组存储,但只显示前十行。当用户点击链接时,用下一组十行替换它们。通过使用全局变量作为缓存,您可以避免重复的 AJAX 回调,这看起来对用户很慢。(显然,这在几十行的情况下比在几千行的情况下效果更好。) - Blazemonger
我认为我不会使用全局变量,而是将所有应该在getEle返回时发生的事情放入$.$ajax回调中。非常感谢! - Otze

0

你的回调函数会在代码的其余部分执行完毕后一段时间内执行。

你需要使用回调函数将值传递回来,就像$.ajax一样。


-1

你的警告最终变成了未定义,因为AJAX调用是异步的。因此,当AJAX调用等待服务器响应时,脚本继续执行警告,在这一点上element[1]尚未定义。

你应该将return element行放在success回调函数内部。


你对异步的事情非常正确,但你确定成功函数中的返回值会起作用吗?我的意思是getEle函数会返回什么? - alinn
我会将Ajax调用设置为同步。 - alinn
1
@alinn,我不会将AJAX调用设置为同步的。那样就完全违反了AJAX的初衷。我会在成功回调中简单地使用AJAX调用的结果。 - Darin Dimitrov
@Darin Dimitrov,我认为同步 AJAX 并没有违背 AJAX 的目的。我只是建议最简单的解决方案。你所建议的方法也不错,只要你不对 AJAX 响应进行大量操作(考虑它会看起来如何)。还可以触发事件,或将回调函数作为参数发送到 myEle 函数(该函数在响应函数内被调用),以使代码看起来更漂亮。 - alinn
@alinn,如果你需要在成功回调中执行很多操作,你可以将它们外部化到一个单独的函数(或插件)中,并通过传递 AJAX 调用的结果来简单地调用它。现在,你的成功回调只需要进行一个简单的函数调用即可。 - Darin Dimitrov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接