首页 > 解决方案 > 减少 Google Apps 脚本中的脚本运行时间?

问题描述

我创建了一个脚本来跟踪远程学习的出勤率。过了一会儿,它超时了,所以我认为我对 Google Classroom API 的调用过多时遇到了问题,但是我没有看到可以更改它以使这些调用脱离循环的方法。

该脚本采用我的应用程序脚本帐户作为合作教师的所有 Google 课堂课程,并使用定时触发器创建一个每日考勤任务,其中有一个问题是“这里”。然后学生应该回答问题,然后另一个触发器在晚上运行该功能以“评分”每个作业并填充我的电子表格,以便学校秘书可以在早上查看它并记录前几天的出勤率。

似乎有瓶颈的部分是我的 getStudentResponses() 函数。我试图通过过滤掉没有提交作业的学生来减少时间,但这还不够。有没有人看到我可以让这更快的方法?我正在阅读有关使用缓存服务的信息,但我不知道如何让它发挥作用。任何帮助,将不胜感激。

var ss = SpreadsheetApp.getActive();
var date = new Date();

/*
creates a button to programmatically create all necessary timed triggers for easy deployment
*/
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Attendance')
      .addItem('Create Triggers', 'createTriggers')
      .addToUi();
}

/*
auto accepts any co-teacher invites
*/
function acceptInvite() {
  try{
    var optionalArgs = {
      userId: "me"
    };
    var invites = Classroom.Invitations.list(optionalArgs);
    for(var i = 0; i < invites.invitations.length; i++) {
      Classroom.Invitations.accept(invites.invitations[i].id);
    }
  }
  catch(e){}
}

/*
populates a spreadsheet with all the classes that the script Google account is a co-teacher of
the sheet has two columns one with the course name and two with the course id
*/
function listCourses() {
  var optionalArgs = {courseStates: "ACTIVE"};
  var response = Classroom.Courses.list(optionalArgs);
  var courses = response.courses;
  var classSheet;
  
  try{
    classSheet = ss.insertSheet("Classes", 0);
    ss.insertSheet("Assignments", 1);
  }
  catch(e) {
    classSheet = ss.getSheetByName("Classes");
  }
  classSheet.clear();
  if (courses && courses.length > 0) {
    for (i = 0; i < courses.length; i++) {
      var course = courses[i];
      classSheet.appendRow([course.name, course.id]);
    }
  }
}

/*
reads the sheet to get all the classes and creates a new array with all the class IDs
*/
function getCourses() {
  var classSheet = ss.getSheetByName("Classes");
  var classList = new Array();
  var range = classSheet.getDataRange();
  var values = range.getValues();
  
  for(var i in values) {
    var row = values[i];
    var courseId = row[1]+"";
    classList.push(Classroom.Courses.get(courseId));
  }
  createTopics(classList);
}

/*
called immediatly after getCourses, creates topics in each class that will contain the daily attendance assignment
*/
function createTopics(classList) {
  for(i = 0; i < classList.length; i++) {
    var topic;
    var resource = {name: "Daily Online Attendance"};
    
    try {
      topic = Classroom.Courses.Topics.create(resource, classList[i].id);
      createAssignment(topic,classList[i]);
    }
    catch(e) {
      if(e == "GoogleJsonResponseException: API call to classroom.courses.topics.create failed with error: Requested entity already exists") {
        var topics = Classroom.Courses.Topics.list(classList[i].id);

        for(j = 0; j < topics.topic.length; j++) {
          if(topics.topic[j].name == "Daily Online Attendance") {
            createAssignment(topics.topic[j], classList[i]);
          }
        }
      }
    }
  }
}

/*
creates an assignment in each class, under each topic
each assignment only has one choice that says "here" and is going to be 'graded' each night to track attendance
*/
function createAssignment(topic,course) {
  var resource = {
    title: "Attendance for "+(date.getMonth()+1)+"/"+date.getDate()+"/2020",
    description: "Please fill this assignment out each day for attendance",
    topicId: topic.topicId,
    state: "PUBLISHED",
    workType: "MULTIPLE_CHOICE_QUESTION",
    multipleChoiceQuestion: {
      "choices": [
        "Here"
      ] 
    }
  };
  try {
    var assignment = Classroom.Courses.CourseWork.create(resource, course.id);
    var sheet = ss.getSheetByName("Assignments");
    sheet.appendRow([course.id,assignment.id]);
  }
  catch(e){}
}

/*
creates a new sheet for each day and logs each assignement
*/
function getStudentResponses() {
  var assignmentSheet = ss.getSheetByName("Assignments");
  var sheet2;
  var response;

  assignmentSheet.sort(1, true);
  
  try{
    sheet2 = ss.insertSheet("Attendance for "+(date.getMonth()+1)+"/"+date.getDate()+"/2020",(ss.getSheets().length-(ss.getSheets().length-2)));
    sheet2.appendRow(["Student Last Name","Student First Name","Grade","Class Name","Assignment Answer"]);
  }
  catch(e) {
    sheet2 = ss.getSheetByName("Attendance for "+(date.getMonth()+1)+"/"+date.getDate()+"/2020");
  }
  
  sheet2.setFrozenRows(1);
  
  var range = assignmentSheet.getDataRange();
  var values = range.getValues();
  
  for(var i in values) {
    var row = values[i];
    var courseId = row[0]+"";
    var courseWorkId = row[1]+"";
    
    try {
      response = Classroom.Courses.CourseWork.StudentSubmissions.list(courseId, courseWorkId);
        
      for(var j in response.studentSubmissions) {
        if(response.studentSubmissions[j].state == "TURNED_IN") {
          try {
            var grade;
            var email = Classroom.UserProfiles.get(response.studentSubmissions[j].userId).emailAddress;
            sheet2.appendRow([Classroom.UserProfiles.get(response.studentSubmissions[j].userId).name.familyName,Classroom.UserProfiles.get(response.studentSubmissions[j].userId).name.givenName,grade,Classroom.Courses.get(courseId).name,response.studentSubmissions[j].multipleChoiceSubmission.answer]);
          }
          catch (e) {}
        }
      }
    }
    catch(e) {}
  }
}

/*
deletes all assignemnts that were created
*/
function deleteAssignments() {
  var assignmentSheet = ss.getSheetByName("Assignments");
  assignmentSheet.sort(1, true);
  var range = assignmentSheet.getDataRange();
  var values = range.getValues();
  
  for(var i in values) {
    var row = values[i];
    var courseId = row[0]+"";
    var courseWorkId = row[1]+"";
    
    try {
      Classroom.Courses.CourseWork.remove(courseId, courseWorkId);
    }
    catch(e) {}
  assignmentSheet.clear();
  }
}

function createTriggers() {
  ScriptApp.newTrigger('getCourses')
      .timeBased()
      .everyDays(1)
      .atHour(6)
      .create();
  
  ScriptApp.newTrigger('getStudentResponses')
      .timeBased()
      .everyDays(1)
      .atHour(22)
      .create();
  
  ScriptApp.newTrigger('deleteAssignments')
      .timeBased()
      .everyDays(1)
      .atHour(23)
      .create();
  
  ScriptApp.newTrigger('listCourses')
      .timeBased()
      .everyDays(1)
      .atHour(21)
      .create();
  
  ScriptApp.newTrigger('acceptInvite')
      .timeBased()
      .everyDays(1)
      .atHour(20)
      .create();
}

标签: performancegoogle-apps-script

解决方案


appendRow很慢,你应该避免在for循环中使用它。而是构建一个数组,然后使用单个setValues调用传递值。

资源

有关的


推荐阅读