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

如何实现多用户多日历月同步的异步循环串行执行?

解决方案

要实现「按月串行同步,每个月内资源串行同步」的需求,核心是把异步操作包装成Promise,再用async/await控制执行顺序:

1. 改造loopThroughResources为Promise版本

将原来的回调式$.post包装成Promise,让整个函数返回Promise,外部可以等待它执行完成:

function loopThroughResources(resourceIds, i, loopStartDate, loopEndDate) {
  // 递归终止条件,返回已完成的Promise
  if (i == resourceIds.length) {
    $("#start_exchange")
      .text("Synchroniseren")
      .removeAttr("disabled")
      .css("cursor", "pointer");
    return Promise.resolve();
  }
  
  const resourceId = resourceIds[i];

  $("#exchange_output").append(
    "Start synchroniseren naar Outlook-agenda van " +
      resourceNames.get(resourceId) +
      " van " +
      loopStartDate +
      " tot " +
      loopEndDate + "...<br>",
  );

  // 封装$.post为Promise
  return new Promise((resolve, reject) => {
    $.post(
      "sync.php",
      {
        resourceId: resourceId,
        startDate: loopStartDate,
        endDate: loopEndDate,
      },
      function (response) {
        $("#exchange_output").append(response);
        // 递归调用下一个资源,等待完成后resolve当前Promise
        loopThroughResources(resourceIds, i + 1, loopStartDate, loopEndDate)
          .then(resolve)
          .catch(reject);
      }
    ).fail(reject); // 处理请求失败场景
  });
}

2. 改造loopThroughMonths为异步函数

将loopThroughMonths改为async函数,遍历月份时逐个await当前月份的资源同步完成,再进入下一个月份:

async function loopThroughMonths(resourceIds, startDate, endDate) {
  const startDateObject = new Date(startDate);
  const endDateObject = new Date(endDate);

  // 计算日期范围跨越的月份数
  const dateRangeMonths = monthDiff(startDateObject, endDateObject);

  if (dateRangeMonths > 0) {
    // 遍历每个月份,用for循环+await实现串行执行
    for (let i = 0; i <= dateRangeMonths; i++) {
      let loopStartDate, loopEndDate;
      
      if (i == 0) {
        // 第一个月:起始为原范围开始,结束为当月最后一天
        loopStartDate = startDate;
        loopEndDate = formatDate(
          lastDayOfMonth(
            startDateObject.getFullYear(),
            startDateObject.getMonth(),
          ),
        );
      } else if (i != dateRangeMonths) {
        // 中间月份:整月范围
        const loopMonth = new Date(
          startDateObject.getFullYear(),
          startDateObject.getMonth() + i,
          1,
        );
        loopStartDate = formatDate(
          firstDayOfMonth(loopMonth.getFullYear(), loopMonth.getMonth()),
        );
        loopEndDate = formatDate(
          lastDayOfMonth(loopMonth.getFullYear(), loopMonth.getMonth()),
        );
      } else {
        // 最后一个月:起始为当月第一天,结束为原范围结束
        loopStartDate = formatDate(
          firstDayOfMonth(
            endDateObject.getFullYear(),
            endDateObject.getMonth(),
          ),
        );
        loopEndDate = endDate;
      }

      // 等待当前月份所有资源同步完成,再进入下一个循环
      await loopThroughResources(resourceIds, 0, loopStartDate, loopEndDate);
    }
  } else {
    // 日期范围在一个月内,直接等待资源同步完成
    await loopThroughResources(resourceIds, 0, startDate, endDate);
  }
}

3. 调用方式

调用时可通过.catch()处理同步异常:

loopThroughMonths(yourResourceIds, yourStartDate, yourEndDate)
  .catch(err => {
    console.error('同步出错:', err);
    // 可添加前端错误提示逻辑
  });

核心逻辑说明

  • 把$.post包装成Promise,让异步操作具备可等待性
  • loopThroughResources递归时,每个步骤都返回Promise,形成完整的异步链路,确保整个月份的资源同步完成后才会resolve
  • loopThroughMonths用async/await配合for循环,强制月份之间串行执行,避免多月份同步同时触发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:44:50