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

Google Apps Script运行缓慢致Google Form异常问题求助

解决Google Form测验生成时的访问冲突与不完整问题

一、核心问题根源

你的脚本直接修改现有表单:先清空所有题目,再逐个添加新题。这个过程中若有用户访问或提交,就会出现题目不全、分数异常、作答被清空的情况。同时脚本多次调用getRange导致运行效率低下,延长了生成时间,进一步加剧了问题。

二、分步解决方案

1. 表单状态管控:生成前禁用访问,完成后恢复

在脚本启动时将表单设为不接受响应,生成完成后再重新开放。用户在生成过程中访问会看到明确提示,无法进入作答流程。

修改createQuiz函数:

function createQuiz() 
{
  const form = FormApp.openById([formID]);
  // 先禁用表单响应,阻止用户访问
  form.setAcceptingResponses(false);
  form.setCustomClosedFormMessage("测验正在更新,请稍后再试。");

  // ---------------------- 原有生成逻辑开始 ----------------------
  const file = SpreadsheetApp.openById([sheetID]);
  const sheet = file.getSheetByName("Questions");
  
  // 一次性读取所有数据到内存,避免重复调用getRange
  const values = sheet.getDataRange().getValues();
  const question_total = sheet.getLastRow() - 1;
  const question_req = 20; 
  const index = questions(question_total, question_req);

  // 清空现有题目
  const items = form.getItems();
  while(items.length > 0){
    form.deleteItem(items.pop());
  }
  
  form.setIsQuiz(true);

  // 从内存数组中提取题目数据,不再调用getRange
  for(let r=0; r<question_req; r++)
  {
    const rowIndex = index[r]; // values第一行是表头,直接用索引取值
    const title = values[rowIndex][0];
    const nchoices = values[rowIndex][1];
    const choices = [values[rowIndex][2], values[rowIndex][3], values[rowIndex][4], values[rowIndex][5]];
    const feedback = values[rowIndex][6];

    createShuffledChoices(form, title, nchoices, choices, feedback)
  }
  // ---------------------- 原有生成逻辑结束 ----------------------

  // 生成完成后重新开放表单
  form.setAcceptingResponses(true);
}

2. 优化脚本性能,缩短生成时间

原脚本循环中多次调用getRange是Google Apps Script的性能瓶颈,改成一次性读取所有数据到内存数组,直接从数组提取信息,能大幅减少运行时间,降低用户在生成过程中访问的概率。

3. 防止并发触发:用锁机制避免多实例冲突

添加脚本锁,确保同一时间只有一个脚本实例在运行,彻底避免多个用户触发脚本导致的表单冲突:

在createQuiz开头补充锁逻辑:

function createQuiz() 
{
  // 获取脚本锁,超时30秒(可根据实际调整)
  const lock = LockService.getScriptLock();
  if (!lock.tryLock(30000)) {
    // 获取锁失败,说明已有实例在运行,直接退出
    console.log("测验正在生成中,请稍后再试");
    return;
  }

  const form = FormApp.openById([formID]);
  form.setAcceptingResponses(false);
  form.setCustomClosedFormMessage("测验正在更新,请稍后再试。");

  // ... 原有生成逻辑 ...

  form.setAcceptingResponses(true);
  // 释放锁
  lock.releaseLock();
}

三、辅助优化:随机索引生成算法

原questions函数效率较低,改用Fisher-Yates洗牌算法生成随机索引,避免循环等待:

function questions(question_total, question_req) {
  // 生成1到question_total的索引数组
  const indices = Array.from({length: question_total}, (_, i) => i + 1);
  // Fisher-Yates洗牌
  for (let i = indices.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [indices[i], indices[j]] = [indices[j], indices[i]];
  }
  // 返回前question_req个随机索引
  return indices.slice(0, question_req);
}

四、效果验证

修改后:

  • 脚本运行时,用户访问表单会看到自定义关闭提示,无法进入作答
  • 脚本运行时间大幅缩短,减少冲突窗口
  • 锁机制确保不会有多个脚本实例同时修改表单,彻底解决作答被清空的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:00:38