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

使用原生JS实现HN克隆时如何进行嵌套AJAX请求?

如何在Hacker News克隆项目中实现嵌套AJAX调用获取新闻详情?

看起来你已经走对路啦——你已经成功拿到了Hacker News Top Stories的ID列表,接下来只需要针对每个ID发起嵌套的AJAX请求,就能拿到每条新闻的详细数据了。我来给你拆解下具体怎么实现,还有一些优化点要注意:

基于原生XMLHttpRequest的实现方案

先顺着你现有的代码逻辑修改,核心是在第一个请求的回调里,为每个新闻ID创建新的AJAX请求:

var apiResult = document.getElementById("apiResult"); 

function apiContent() { 
  var url_end = 'https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty'; 
  var apiCall = new XMLHttpRequest(); 

  apiCall.onload = function() { 
    if(this.status == 200) { 
      var storyIds = JSON.parse(apiCall.responseText); 
      // 先取前20条测试,避免一次性发起500个请求导致性能问题
      var topStoryIds = storyIds.slice(0, 20); 

      topStoryIds.forEach(function(storyId) {
        // 为每个新闻ID创建新的AJAX实例
        var storyRequest = new XMLHttpRequest();
        var storyUrl = `https://hacker-news.firebaseio.com/v0/item/${storyId}.json?print=pretty`;

        storyRequest.onload = function() {
          if(this.status === 200) {
            var storyData = JSON.parse(this.responseText);
            // 把新闻数据渲染到页面
            renderStory(storyData);
          } else {
            console.error(`获取ID为${storyId}的新闻失败:${this.status}`);
          }
        };

        // 处理请求错误
        storyRequest.onerror = function() {
          console.error(`请求ID为${storyId}的新闻时发生错误`);
        };

        storyRequest.open('GET', storyUrl, true);
        storyRequest.send();
      });
    } else {
      console.error(`获取Top Stories列表失败:${this.status}`);
    }
  }; 

  apiCall.onerror = function() {
    console.error("请求Top Stories列表时发生错误");
  };

  apiCall.open('GET', url_end, true); 
  apiCall.send(); 
}

// 辅助函数:渲染单条新闻到页面
function renderStory(story) {
  var storyElement = document.createElement('div');
  storyElement.innerHTML = `
    <h3><a href="${story.url}" target="_blank">${story.title}</a></h3>
    <p>作者:${story.by} | 评分:${story.score} | 评论数:${story.descendants || 0}</p>
    <hr>
  `;
  apiResult.appendChild(storyElement);
}

// 启动数据获取
apiContent();

关键注意点:

  • 嵌套回调的时机:必须在第一个请求的onload回调里发起后续请求,确保已经拿到了新闻ID列表
  • 错误处理:给每个请求都加上错误捕获,避免单个请求失败导致整个流程卡住
  • 性能控制:HN的Top Stories有500个ID,一次性发起所有请求会很慢甚至被限流,建议先取前20条测试

更简洁的现代方案:使用Fetch + Async/Await

如果你想避免“回调地狱”,可以用ES6+的fetchAPI和async/await语法,让异步代码更易读:

var apiResult = document.getElementById("apiResult"); 

async function apiContent() {
  try {
    // 第一步:获取Top Stories的ID列表
    const topStoriesResponse = await fetch('https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty');
    if (!topStoriesResponse.ok) throw new Error(`获取Top Stories失败:${topStoriesResponse.status}`);
    
    const storyIds = await topStoriesResponse.json();
    const topStoryIds = storyIds.slice(0, 20);

    // 第二步:并行发起所有新闻详情请求
    const storyPromises = topStoryIds.map(storyId => 
      fetch(`https://hacker-news.firebaseio.com/v0/item/${storyId}.json?print=pretty`)
        .then(res => {
          if (!res.ok) throw new Error(`获取ID为${storyId}的新闻失败:${res.status}`);
          return res.json();
        })
    );

    // 等待所有请求完成
    const stories = await Promise.all(storyPromises);
    
    // 批量渲染新闻
    stories.forEach(story => renderStory(story));
  } catch (error) {
    console.error(error.message);
  }
}

function renderStory(story) {
  var storyElement = document.createElement('div');
  storyElement.innerHTML = `
    <h3><a href="${story.url}" target="_blank">${story.title}</a></h3>
    <p>作者:${story.by} | 评分:${story.score} | 评论数:${story.descendants || 0}</p>
    <hr>
  `;
  apiResult.appendChild(storyElement);
}

apiContent();

这个方案的优势:

  • async/await让异步代码看起来像同步逻辑,可读性大幅提升
  • Promise.all可以并行处理所有新闻请求,比逐个发起请求更快
  • 统一的try/catch块处理所有错误,代码更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:40:32