【问题标题】:AJAX asynchronous call -- can't return data with callback?AJAX 异步调用——不能用回调返回数据?
【发布时间】:2013-02-06 15:03:07
【问题描述】:

我下面有这段代码,我想在ajax调用的成功函数中返回数据。当然,如果我执行 async:false 并直接返回它,我会得到它,但我不想这样做。

如果我像现在这样运行它,信息变量是未定义的(如果我执行 async:false,它会获取信息,所以问题不是数据的内容)。

我只是不明白为什么它不起作用,我用谷歌搜索了回调函数,看来我做得对......

function PUT_updateSystem(id) {
    var system= {};
    system= getSystemInformation(name, function(data){
                                var system = data;
                                return system;});

    var information = system.info;

}
// Returns system information
function getSystemInformation(name,callback){
    $.ajax({
        type:"GET",
        url: getUrl(),
        cache: false,
        dataType: "json",
        success: function(data){
            callback(data);
        }
    });
}

编辑: 将我的代码更改为我目前拥有的代码

我正在使用这些数据生成一个 jsTree,并为该树创建 json 数据,我正在执行上述操作,但将信息变量放入一个对象并对其进行迭代以创建节点。问题不在于树,所以我不会在这里包括它。我什至可以把这个逻辑拿出来进行测试。

那么发生了什么,

  1. 页面开始加载
  2. 我执行上述操作
  3. 信息被放入 javascript 对象中
  4. 我遍历了 javascript 对象。
  5. 我收到错误“无法读取未定义的属性‘长度’”
  6. 在调试时,我发现它跳过了 system.done。这是有道理的,因为它可能不会完成。

有没有办法等待它完成?

编辑: 提供更多信息

// 在一个被调用的文件中 loadinfo.js

// Returns system information promise
function getSystemInformation(){
    return $.ajax({
        type:"GET",
        url: getUrl(), // url is defined somewhere else
        cache: false,
        dataType: "json"
    });
}

// IN A FILE CALLED tree.js
// I have other variables from loadinfo.js that are here so they can communicate fine

    $.when(getSystemInformation(), $.Deferred(function(deferred) {
        $(deferred.resolve);
    })).done(function(data) {
        mapCache["system"] = data;
        console.log("defer DONE!!");

$.each(mapCache["system"], function(index, system) {
            var children = doDisplayChildNodes(system.name);
            ...
                    ...
});

我在 $.each 中所做的只是从 mapCache["system"] 获取数据并创建一个“jstree”节点。我做了一个子函数来做同样的事情,因为我有与每个系统关联的子节点。所有这些逻辑都有效,因为当我将 ajax 调用设为“async:false”时它可以正常工作——所以我不会发布它。

我在 $.each 期间收到无法读取未定义的属性“长度”。这很奇怪,因为我在 mapCache 上设置了“Watch”,并且在加载所有内容后, mapCache 填充了正确的值。我正在使用谷歌浏览器调试。

【问题讨论】:

  • 你怎么知道你的回调“不起作用”?对我来说它有效,但没有什么特别之处。
  • 这是什么功能! ? getUrl() 是做什么的,它带你到什么 url,在那个 url 上的代码是什么?
  • 函数在调用中定义。它返回检索到的数据。 getUrl() 与问题无关,是从代码中抽象出来的——它只是用于此请求的 url。 PUT_updateSystem 在我的实际实现中继续进行,但正是这部分我提出了我需要帮助的问题。
  • #5 发生在哪里?
  • 当我加载页面时,我正在运行这个函数并将值放入 javascript 对象中,然后我正在呈现 HTML。当我渲染 html 以显示我正在制作的树时,我需要遍历我返回的值(现在位于 javascript 对象中),然后我得到这个错误。

标签: jquery ajax callback


【解决方案1】:

您使用了回调,但您仍然将其用于同步逻辑而不是异步。尝试这样做:

function PUT_updateSystem(id) {
    var system = getSystemInformation(name);
    system.done(function(data){
        var information = data.info;
        // do stuff with `information` here, not elsewhere.
    });
}
// Returns system information promise
function getSystemInformation(name){
    return $.ajax({
        type:"GET",
        url: getUrl(),
        cache: false,
        dataType: "json"
    });
}

【讨论】:

  • Kevin,我发现这个答案最适合我的问题,但我只是遇到了一个问题,我根据这个 AJAX 调用渲染 HTML 元素——当我在 firebug 中调试错误时,它会跳过“system.done”,它正在填充我需要的 html 数据。我创建了一个赏金来帮助解决这个问题。
  • @envinyater,关于您的调试问题,您是否尝试过在 system.done 回调中设置断点?
  • @marty,是的,我有。当我调试时,它永远不会命中它,但它必须在页面呈现后命中它,因为我为对象设置了一个监视并且它工作得很好。
【解决方案2】:
function PUT_updateSystem(id) {
    var system= {};
    system= getSystemInformation(name, callbackfunction);

    var information = system.info;

}
//callbackfuncion
function callbackfunction(data){
    var system = data;
    return system;
}
// Returns system information
function getSystemInformation(name,callback){
    $.ajax({
        type:"GET",
        url: getUrl(),
        cache: false,
        dataType: "json",
        success: function(data){
            window[callback](data);
        }
    });
}

只是代替callback(data);
window[callback](data);
并将函数名作为变量

【讨论】:

  • 我刚试过,还是不行。我收到一个错误:未捕获的 TypeError: Property 'function callbackFunction(data){ var system =data;返回数据;对象 [object Window] 的 }' 不是函数
  • 为什么要使用全局变量进行回调?哎呀。
【解决方案3】:

异步意味着当 PUT_updateSystem 已经完成时调用回调。

当您调用 getSystemInformation 时向服务器发出请求,但在它被调用后该函数继续 var information = system.info;在服务器有时间响应so system.info之前;尚未设置。如果您的浏览器带有开发工具 IE、带有 firebug 插件的 firefox、Chrome,您只需按 F12。运行下面的代码,你可能会明白回调是什么意思,在控制台中查看消息(alert 不起作用,因为它会暂停 JavaScript 执行。

function PUT_updateSystem(id) {
    var system= {};
    system= getSystemInformation(name, function(data){
                                var system = data;
// you re declare system here so it' actually not set
// if you want to set system in PUT_updateSystem you should
// do system = data; without the val
console.log("this comes last");
console.log("data is returned now",data);
                                return system;});
console.log("This comes first");
    var information = system.info;

}
// Returns system information
function getSystemInformation(name,callback){
    $.ajax({
        type:"GET",
        url: getUrl(),
        cache: false,
        dataType: "json",
        success: function(data){
console.log("this comes second");
            callback(data);
        }
    });
}

【讨论】:

  • return system; 应该被删除/注释掉,它没有任何作用。
  • None 如果它做任何事情:) 我认为 OP 尝试使用闭包获取系统变量中的数据,但随后将设置它的值返回给一个变量并重新声明它。但是由于它是异步的,所以没有任何变量在 OP 期望的时候设置。
  • 对,我的意思是你的代码的其余部分将按预期工作,除了返回。
  • 我复制并粘贴了 OPs 代码,因为它没有意义,在其中放一些 console.log 来演示执行顺序。它不会在任何有用的时间设置系统
【解决方案4】:

你做得不对,回调不返回任何数据。 JavaScript 中没有等待语句。异步调用被执行,然后 JavaScript 继续处理其余代码。

你的代码应该是

function PUT_updateSystem(id) {
    var system= {};

    function processData(data) {
        var information = data.info;
        alert("Do next step");
    }

    system = getSystemInformation(name, processData);
}

将您的逻辑分为两个步骤。

  1. 进行 Ajax 调用
  2. 处理回调中的数据

【讨论】:

  • 如果他们不返回任何数据,那么我可以用变量“信息”做什么——它不会去任何地方,我也无法返回——我该如何使用它在我原来的功能中?
  • 您将函数分解为多个部分。第一部分进行调用,第二部分处理它。
  • @envinyater 你不能。你真的需要弄清楚异步代码是如何工作的,它根本不像你想象的那样工作。
  • @envinyater 这里是一个例子:developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/…
猜你喜欢
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
  • 2017-03-02
  • 2014-10-29
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
相关资源
最近更新 更多