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

JavaScript实现拆分日期区间调用API,获首个有数据段即停止请求

问题分析与修复方案

你的代码主要存在以下几个问题:

  • 日期变量逻辑错误:你把startDate和endDate搞反了,startDate应该是更早的日期,endDate是较晚的日期,否则日期范围计算和API请求都会出错。
  • 异步请求未正确处理:requestToDataNews返回的是Promise,你直接通过newsData.is_success判断是无效的,Promise对象本身没有这个属性,必须用await或.then()等待请求完成后再处理数据。
  • 日期区间计算错误:用subtract('months', 2)不能精确得到90天的区间,应该用subtract(90, 'days');同时每次循环需要将endDate更新为当前区间的startDate,才能正确往前推移90天。
  • 未实现"获取到首个有数据的区间就停止"的逻辑:原循环会跑完所有区间,没有在拿到有效数据后终止循环。
  • Loading状态管理混乱:每个请求的finally都会关闭loading,导致循环中后续请求还在进行时loading就被关掉了。

修复后的代码

async function fetchFirstValidNewsData(originalStart, originalEnd) {
  // 确保日期顺序正确,start是更早的日期
  const startDate = moment.min(moment(originalStart), moment(originalEnd));
  const endDate = moment.max(moment(originalStart), moment(originalEnd));
  const differentDays = endDate.diff(startDate, 'days');
  const currentNewsData = [];

  // 只处理90-365天的范围
  if (differentDays <= 90 || differentDays > 365) {
    // 范围小于等于90天直接请求
    const data = await requestToDataNews(startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD'));
    if (data.is_success) {
      currentNewsData.push(...data.data);
    }
    return currentNewsData;
  }

  commit('loadingBar', true);
  let currentEnd = endDate.clone();
  const maxLoops = Math.ceil(differentDays / 90);

  try {
    for (let i = 0; i < maxLoops; i++) {
      // 计算当前区间的开始日期:当前结束日期往前推90天
      const currentStart = currentEnd.clone().subtract(90, 'days');
      // 确保不超过原始的开始日期
      const actualStart = moment.max(currentStart, startDate);
      
      const newsData = await requestToDataNews(actualStart.format('YYYY-MM-DD'), currentEnd.format('YYYY-MM-DD'));
      
      if (newsData.is_success && newsData.data.length > 0) {
        currentNewsData.push(...newsData.data);
        // 拿到有效数据,终止循环
        break;
      }

      // 没有数据,将当前结束日期更新为当前区间的开始日期前一天,继续往前找
      currentEnd = actualStart.clone().subtract(1, 'days');
      // 如果已经到了原始开始日期,停止循环
      if (currentEnd.isBefore(startDate)) break;
    }
  } catch (error) {
    console.error('请求新闻数据失败:', error);
    // 可在此添加错误提示等逻辑
  } finally {
    commit('loadingBar', false);
  }

  return currentNewsData;
}

// 原请求函数修正:移除内部的loading状态变更,统一由外部管理
function requestToDataNews(startDate, endDate) {
  return new Promise((resolve, reject) => {
    http.get(`/test=&start_date=${startDate}&end_date=${endDate}`, { timeout: 40000 })
      .then((response) => {
        if (response.data.response_code === 200) {
          resolve(response.data);
        } else {
          reject(response.data);
        }
      })
      .catch((error) => {
        reject(error);
      });
  });
}

// 调用示例
fetchFirstValidNewsData('2021-12-27', '2022-12-27');

关键改动说明

  1. 日期顺序校正:用moment.min和moment.max确保startDate始终早于endDate,避免传入顺序错误导致的问题。
  2. 异步请求处理:使用async/await等待请求完成,确保能正确获取到返回的is_success和data字段。
  3. 正确的区间推移:每次循环将currentEnd更新为上一个区间的startDate前一天,确保区间不重叠且覆盖整个范围;同时添加判断,避免超过原始的开始日期。
  4. 终止逻辑实现:在拿到is_success为true且数据不为空时,立即break终止循环,符合需求。
  5. Loading状态统一管理:将loading的开启和关闭移到循环外部的try/finally中,确保所有请求完成后才关闭loading。
  6. 请求函数优化:移除请求函数内部的commit('loadingBar', false),避免多次请求时混乱的loading状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 15:05:20