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

异步函数返回值问题:如何让XMLHttpRequest/fetch向父函数返回数据

异步请求返回undefined的问题解决及Fetch API用法

问题根源

你遇到的bookss输出undefined的核心原因是XMLHttpRequest是异步操作:

  • fetchBooks函数执行到xhr.send()后就直接结束了,默认返回undefined;
  • onload回调里的return books是在请求完成后才触发的,这个返回值根本传不到homepage的bookss变量里。

修复XMLHttpRequest版本

用Promise包装异步操作,让fetchBooks返回一个Promise,再通过async/await或者.then()获取结果:

function fetchBooks() {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", "url");
    xhr.onload = () => {
      if (xhr.status === 200) {
        const books = [];
        // 注意每次创建新的book对象,避免全局变量引用问题
        const book = {
          name: book_name,
          id: book_id,
          genre: book_genre,
          language: book_language,
          date: book_date
        };
        books.push(book);
        console.log(books);
        resolve(books); // 请求成功时传递结果
      } else {
        reject(new Error(`请求错误: ${xhr.status}`));
      }
    };
    // 处理网络错误
    xhr.onerror = () => reject(new Error("网络请求失败"));
    xhr.send();
  });
}

// 父函数用async/await调用
async function homepage() {
  // do stuff
  try {
    const bookss = await fetchBooks();
    console.log(bookss);
  } catch (err) {
    console.error(err);
  }
}

Fetch API实现方案

Fetch本身基于Promise,写法更简洁,解析HTML可以用DOMParser:

async function fetchBooks() {
  try {
    const response = await fetch("url");
    // 检查请求是否成功
    if (!response.ok) {
      throw new Error(`请求错误: ${response.status}`);
    }
    // 获取HTML文本内容
    const htmlText = await response.text();
    // 解析HTML为DOM对象
    const parser = new DOMParser();
    const doc = parser.parseFromString(htmlText, "text/html");
    
    const books = [];
    // 示例:假设从class为book-item的元素中提取图书数据
    const bookItems = doc.querySelectorAll(".book-item");
    bookItems.forEach(item => {
      const book = {
        name: item.querySelector(".book-name").textContent.trim(),
        id: item.dataset.bookId,
        genre: item.querySelector(".book-genre").textContent.trim(),
        language: item.querySelector(".book-lang").textContent.trim(),
        date: item.querySelector(".book-date").textContent.trim()
      };
      books.push(book);
    });
    
    return books;
  } catch (err) {
    console.error(err);
    throw err; // 抛出错误让调用者处理
  }
}

// 父函数调用方式
async function homepage() {
  // do stuff
  try {
    const bookss = await fetchBooks();
    console.log(bookss);
  } catch (err) {
    console.error(err);
  }
}

额外注意事项

  • 原代码中book变量未声明,会变成全局变量,导致所有push的都是同一个对象的引用,必须每次创建新的book对象;
  • 所有异步操作的结果都必须通过Promise链式调用或async/await获取,不能直接同步赋值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:52:51