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

JavaScript中创建Booking对象实例的异步请求返回问题

你的问题核心是没搞明白JavaScript里异步操作的执行逻辑——XMLHttpRequest是异步的,getBooking函数在调用request.send()后就直接结束了,返回undefined,而你在onload回调里的return根本传不到函数外面,所以const booking = getBooking('1')拿到的是undefined,自然访问booking.id会报错。

不用全局变量的话,有两种常用的解决方式:


方法一:用Promise封装异步请求(推荐,更符合现代JS写法)

把getBooking改成返回一个Promise,这样就能通过async/await或者.then()来获取异步返回的Booking实例:

// 优化Booking构造函数,直接传data对象更简洁
function Booking(data) {
  this.id = data.id;
  this.retailer_id = data.retailer_id;
  this.app_date = data.app_date;
}

function getBooking(booking_id) {
  return new Promise((resolve, reject) => {
    let request = new XMLHttpRequest();
    let url = prefix.toString() + 'bookings/' + booking_id;
    request.open('GET', url, true);
    request.onload = function() {
      if (request.status >= 200 && request.status < 400) {
        let data = JSON.parse(this.response);
        // 解析成功就返回Booking实例
        resolve(new Booking(data));
      } else {
        // 请求失败抛出错误
        reject(new Error(`请求失败,状态码:${request.status}`));
      }
    };
    // 处理网络错误
    request.onerror = function() {
      reject(new Error('网络请求出错'));
    };
    request.send();
    console.log("Request sent.");
  });
}

// 调用时用async/await(需在async函数内)
let button = document.getElementById('button');
button.addEventListener('click', async function() {
  try {
    const booking = await getBooking('1');
    console.log(booking.id);
  } catch (err) {
    console.error('获取预订信息失败:', err);
  }
});

方法二:使用回调函数

如果你暂时不想用Promise,也可以给getBooking传一个回调函数,请求完成后调用这个回调把Booking实例传过去:

function Booking(id, retailer_id, app_date) {
  this.id = id;
  this.retailer_id = retailer_id;
  this.app_date = app_date;
}

function getBooking(booking_id, callback) {
  let request = new XMLHttpRequest();
  let url = prefix.toString() + 'bookings/' + booking_id;
  request.open('GET', url, true);
  request.onload = function() {
    let data = JSON.parse(this.response);
    if (request.status >= 200 && request.status < 400) {
      const booking = new Booking(data.id, data.retailer_id, data.app_date);
      // 调用回调,传递实例
      callback(null, booking);
    } else {
      // 出错时传递错误信息
      callback(new Error(`请求失败,状态码:${request.status}`));
    }
  };
  request.onerror = function() {
    callback(new Error('网络请求出错'));
  };
  request.send();
  console.log("Request sent.");
}

// 调用时传入回调
let button = document.getElementById('button');
button.addEventListener('click', function() {
  getBooking('1', function(err, booking) {
    if (err) {
      console.error('获取失败:', err);
      return;
    }
    console.log(booking.id);
  });
});

另外提一句,现在更推荐用fetch API代替XMLHttpRequest,写法更简洁:

function Booking(data) {
  this.id = data.id;
  this.retailer_id = data.retailer_id;
  this.app_date = data.app_date;
}

async function getBooking(booking_id) {
  const url = prefix.toString() + 'bookings/' + booking_id;
  const response = await fetch(url);
  if (!response.ok) {
    throw new Error(`请求失败:${response.status}`);
  }
  const data = await response.json();
  return new Booking(data);
}

// 调用方式和方法一一致
button.addEventListener('click', async function() {
  try {
    const booking = await getBooking('1');
    console.log(booking.id);
  } catch (err) {
    console.error(err);
  }
});

内容的提问来源于stack exchange,提问作者Joshua Munn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 04:25:16