You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何打印XMLHttpRequest请求响应时返回undefined?

为什么你的HttpRequest get方法总是返回undefined?

嘿,我来帮你把这个问题掰明白——核心原因其实是AJAX请求是异步执行的,这也是你用return拿不到结果的关键所在。咱们一步步拆解你的代码问题:

先看第一个版本的代码问题

你最开始的代码里,犯了两个关键错误:

  1. 你在get方法最后直接return callback;,但这时候AJAX请求还在后台跑呢!因为open的第三个参数是true(异步模式),代码不会等待请求完成,会直接跳过请求流程执行return,这时候callback还是你传入的初始值(或者undefined),所以console.log自然输出undefined。
  2. 你在onreadystatechange回调里写callback = httpRequest.responseText;是错的,应该是调用这个回调函数,把结果传进去,而不是给变量赋值。

再看第二个版本的代码问题

你修改后尝试在回调里return httpRequest.responseText;,但这个return只属于onreadystatechange这个内部函数,和外层的get方法没关系!外层的get方法在发送请求后就已经执行完毕了,根本等不到这个内部函数的返回值,所以get方法默认返回undefined,console.log还是拿不到结果。

为什么return不能替代callback?

这就得说清楚异步的本质:当你发送异步AJAX请求时,浏览器会把这个请求放到后台处理,同时继续执行后面的代码。等请求完成(拿到响应)后,才会触发onreadystatechange回调。这时候外层的get方法早就跑完了,你根本没法从get方法直接return还没生成的响应结果。

简单说:同步代码是按顺序一步步走,异步代码是“先去干活,干完了通知我”,你不能在“干活”的时候就想要结果。

正确的写法示例

方式1:正确使用回调函数

var HttpRequest = function() {
  this.get = function(url, callback) {
    var httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = function() {
      // 先判断请求是否完成
      if(httpRequest.readyState == 4) {
        if(httpRequest.status == 200) {
          // 请求成功,调用回调把结果传进去
          callback(null, httpRequest.responseText);
        } else {
          // 请求失败,也要把错误传给回调
          callback(new Error(`请求失败,状态码:${httpRequest.status}`), null);
        }
      }
    };
    httpRequest.open("GET", url, true);
    httpRequest.send(null);
  };
};

var request = new HttpRequest();
// 使用时传入回调函数处理结果
request.get("https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=BTC,USD", function(error, response) {
  if(error) {
    console.error(error);
    return;
  }
  console.log(response); // 这里才能拿到正确的响应内容
});

方式2:用Promise(更现代的写法)

现在大家更倾向于用Promise来处理异步操作,代码更清晰,还能避免回调地狱:

var HttpRequest = function() {
  this.get = function(url) {
    // 返回一个Promise对象
    return new Promise(function(resolve, reject) {
      var httpRequest = new XMLHttpRequest();
      httpRequest.onreadystatechange = function() {
        if(httpRequest.readyState == 4) {
          if(httpRequest.status == 200) {
            // 请求成功,用resolve返回结果
            resolve(httpRequest.responseText);
          } else {
            // 请求失败,用reject返回错误
            reject(new Error(`请求失败,状态码:${httpRequest.status}`));
          }
        }
      };
      httpRequest.open("GET", url, true);
      httpRequest.send(null);
    });
  };
};

var request = new HttpRequest();
// 用then处理成功,catch处理失败
request.get("https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=BTC,USD")
  .then(function(response) {
    console.log(response);
  })
  .catch(function(error) {
    console.error(error);
  });

// 或者用async/await(需要在async函数中使用)
async function fetchBTCPrice() {
  try {
    var response = await request.get("https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=BTC,USD");
    console.log(response);
  } catch(error) {
    console.error(error);
  }
}
fetchBTCPrice();

内容的提问来源于stack exchange,提问作者Jordan Baron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:06:49