首页 > 解决方案 > 访问对象需要setTimeout?

问题描述

我以前没有遇到过这种情况,搜索也没有找到答案。我有一个 ajax 调用可以拉入一个 javascript 对象。

var order = checkOrder();
console.log("t1: ", order);
setTimeout(function() {
    console.log("t2: ", order.responseText);
    console.log("t3: ", order.statusText);
    console.log((order.responseText != '') ? order.responseText : order.statusText);
}, 100);

function checkOrder() {
    return $.get('SCRIPTPATH', function(data) { return data; });
}

我无法弄清楚的奇怪部分是第一个 console.log 吐出正确的数据,表明“订单”实际上设置为正确的对象数据,但是当我尝试访问数据时它是未定义的。只有当我将它包装在不小于 100 的 setTimeout 函数中时,它才会为这些对象值输出正确的数据。

有谁知道为什么会发生这种情况?再次将 order 变量设置为第一个 console.log 输出所有正确的数据,除非我将它们包装在超时函数中,否则它之后的唯一数据会尝试访问未定义的对象值。

控制台中的输出(展开对象,以便您可以看到数据值):

t1:  {…}
    ​abort: function abort()​
    always: function always()​
    catch: function catch()​
    done: function add()​
    fail: function add()​
    getAllResponseHeaders: function getAllResponseHeaders()​
    getResponseHeader: function getResponseHeader()​
    overrideMimeType: function overrideMimeType()​
    pipe: function pipe()​
    progress: function add()​
    promise: function promise()
    ​
    readyState: 4
    ​
    responseText: "OK"
    ​
    setRequestHeader: function setRequestHeader()​
    state: function state()
    ​
    status: 200
    ​
    statusCode: function statusCode()
    ​
    statusText: "OK"
    ​
    then: function then()​
    <prototype>: Object { … }

t2:  undefined
t3:  undefined
undefined

checkOrder 函数使用 jQuery $.get() 并且我检查了 ajaxSubmitComplete 或类似的代码的其余部分,但没有类似的东西。1/10 秒的延迟没什么大不了的,但不喜欢必须将所有后续代码包装在超时函数中的想法。

根据 mgarcia 的回答,这里更新了似乎可以工作的代码(确定是服务器脚本给出的成功响应):

checkOrder().then(function(order) {
    if(order == "OK") {
        //proceed with order
    }
    else {
        //something went wrong
    }
});

function checkOrder() {
    return $.get('SCRIPTPATH', function(data) { return data; });
}

标签: javascriptjquery

解决方案


ajax 是异步的。你有一个竞争条件,设置超时正在工作(现在),因为你的 ajax 在超时用完之前返回。如果您的服务器端调用花费更长的时间,它将无法正常工作(everythign 仍然是未定义的)

您可以编写一个处理来自 ajax 的响应并将其传递给 ajax 调用的函数,而不是仅仅返回数据并指望它在下一行可用。

function handleData = function(order) { 
    console.log("t2: ", order.responseText);
    console.log("t3: ", order.statusText);
    console.log((order.responseText != '') ? order.responseText : order.statusText);
}

function checkOrder() {
    return $.get('SCRIPTPATH', handleData);
}

推荐阅读