Javascript 使用XMLHttpRequest解析JSON时返回空值

Javascript 使用XMLHttpRequest解析JSON时返回空值,javascript,json,typescript,Javascript,Json,Typescript,我现在一直在尝试从API解析一点JSON,当我使用 xmlHttp.open('GET', url, false); 但当我后来想使用请求超时来扩展代码时,我的函数开始返回空值 这是执行实际解析的函数: xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { obj = JSON.pars

我现在一直在尝试从API解析一点JSON,当我使用

xmlHttp.open('GET', url, false);
但当我后来想使用请求超时来扩展代码时,我的函数开始返回空值

这是执行实际解析的函数:

xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState == 4) {
          if (xmlHttp.status == 200) {
              obj = JSON.parse(xmlHttp.responseText);
              console.log(obj);
           }
      }
  };
当我在这里使用console.log记录返回的对象时,通常会将JSON打印到控制台,但稍后在我的函数中,我会返回obj变量,但它总是空的

以下是整个功能:

static Parse(url: string): Object{
  Asserts.isUrl(url, 'URL is invalid');
  var obj = new Object();
  var xmlHttp = new XMLHttpRequest();

  xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState == 4) {
          if (xmlHttp.status == 200) {
              obj = JSON.parse(xmlHttp.responseText);
              //console.log(obj);
           }
      }
  };

  xmlHttp.open('GET', url, true);
  xmlHttp.timeout = 2000;
  xmlHttp.ontimeout = function () {
    xmlHttp.abort();
    throw new Error("Request Timed Out.");
  };
  xmlHttp.send();

  return obj;
}
Parse('http://foobar', function(obj) => {
    // TODO: do something with obj here
    console.log(obj);
});
static Parse(url: string, onSuccess: Function): Object{
  Asserts.isUrl(url, 'URL is invalid');

  var xmlHttp = new XMLHttpRequest();

  xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState == 4) {
          if (xmlHttp.status == 200) {
              var obj = new Object();
              obj = JSON.parse(xmlHttp.responseText);
              onSuccess(obj)
           }
      }
  };

  xmlHttp.open('GET', url, true);
  xmlHttp.timeout = 2000;
  xmlHttp.ontimeout = function () {
    xmlHttp.abort();
    throw new Error("Request Timed Out.");
  };
  xmlHttp.send();

}
我最初认为它与Javascript中的作用域有关,但现在在这里停留了几个小时而没有任何进展之后,我就不知所措了


正如我在xmlHttp.onreadystatechange=函数()中提到的,console.log实际上记录了正确的值。只是在函数开始时创建的obj变量没有得到值。

AJAX是异步的。这意味着,
onreadystatechange
函数将在更晚的阶段调用,可能是在您已经从
Parse
方法返回之后。因此,您不应该试图从
Parse
方法返回
obj
。您希望让
Parse
方法获取一个表示回调函数的附加参数,您将在
onreadystatechange
事件中调用该回调函数,并将其传递给结果对象

我的意思是:

static Parse(url: string, done: (obj: any) => void): void {
    Asserts.isUrl(url, 'URL is invalid');
    var xmlHttp = new XMLHttpRequest();

    xmlHttp.onreadystatechange = function() {
        if (xmlHttp.readyState == 4) {
            if (xmlHttp.status == 200) {
                var obj = JSON.parse(xmlHttp.responseText);
                // Pass the resulting object to the callback function
                done(obj);
            }
        }
    };

    xmlHttp.open('GET', url, true);
    xmlHttp.timeout = 2000;
    xmlHttp.ontimeout = function () {
        xmlHttp.abort();
        throw new Error("Request Timed Out.");
    };
    xmlHttp.send();
}
下面是如何调用
Parse
函数:

static Parse(url: string): Object{
  Asserts.isUrl(url, 'URL is invalid');
  var obj = new Object();
  var xmlHttp = new XMLHttpRequest();

  xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState == 4) {
          if (xmlHttp.status == 200) {
              obj = JSON.parse(xmlHttp.responseText);
              //console.log(obj);
           }
      }
  };

  xmlHttp.open('GET', url, true);
  xmlHttp.timeout = 2000;
  xmlHttp.ontimeout = function () {
    xmlHttp.abort();
    throw new Error("Request Timed Out.");
  };
  xmlHttp.send();

  return obj;
}
Parse('http://foobar', function(obj) => {
    // TODO: do something with obj here
    console.log(obj);
});
static Parse(url: string, onSuccess: Function): Object{
  Asserts.isUrl(url, 'URL is invalid');

  var xmlHttp = new XMLHttpRequest();

  xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState == 4) {
          if (xmlHttp.status == 200) {
              var obj = new Object();
              obj = JSON.parse(xmlHttp.responseText);
              onSuccess(obj)
           }
      }
  };

  xmlHttp.open('GET', url, true);
  xmlHttp.timeout = 2000;
  xmlHttp.ontimeout = function () {
    xmlHttp.abort();
    throw new Error("Request Timed Out.");
  };
  xmlHttp.send();

}

因此,基本上,当您编写一个使用异步AJAX调用的javascript应用程序时,您应该停止考虑将一个接一个地调用并返回值的顺序函数。您应该开始考虑回调。

您需要将回调传递给函数:

static Parse(url: string): Object{
  Asserts.isUrl(url, 'URL is invalid');
  var obj = new Object();
  var xmlHttp = new XMLHttpRequest();

  xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState == 4) {
          if (xmlHttp.status == 200) {
              obj = JSON.parse(xmlHttp.responseText);
              //console.log(obj);
           }
      }
  };

  xmlHttp.open('GET', url, true);
  xmlHttp.timeout = 2000;
  xmlHttp.ontimeout = function () {
    xmlHttp.abort();
    throw new Error("Request Timed Out.");
  };
  xmlHttp.send();

  return obj;
}
Parse('http://foobar', function(obj) => {
    // TODO: do something with obj here
    console.log(obj);
});
static Parse(url: string, onSuccess: Function): Object{
  Asserts.isUrl(url, 'URL is invalid');

  var xmlHttp = new XMLHttpRequest();

  xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState == 4) {
          if (xmlHttp.status == 200) {
              var obj = new Object();
              obj = JSON.parse(xmlHttp.responseText);
              onSuccess(obj)
           }
      }
  };

  xmlHttp.open('GET', url, true);
  xmlHttp.timeout = 2000;
  xmlHttp.ontimeout = function () {
    xmlHttp.abort();
    throw new Error("Request Timed Out.");
  };
  xmlHttp.send();

}

并使用回调参数调用函数。

如何使函数等待onreadystatechange并返回正确的值?或者还有其他更好的解决方案吗?如果你让它等待,那么你就完全扼杀了AJAX的全部目的,而AJAX本来就是异步的。有关如何编写
Parse
函数以使其不返回任何值而使用回调的示例,请参阅我的更新答案。我正在构建一个库,该库正在致力于API。因此,这种方法仍然适用于该目的?另外,您是否有任何我可以阅读的关于同步和异步之间的区别的资源?是的,使用回调是编写异步代码的正确方法。你将组织你的库方法,使它们与回调一起工作。那么我是否需要让我的当前函数返回一个对象?难道我不能让它变成一个空白,完全依赖回调吗?