首页 > 解决方案 > 确保执行 appendRow 并从最后一行返回数据,同时处理与谷歌应用脚​​本的并发性

问题描述

我有一个 html 表单,它获取数据(学生观察)并将该数据保存到电子表格中,它应该是一个函数。生成一个 id b. 将该行附加到电子表格(学生观察)中,包括 id c。通过检索保存在工作表 d 上的最后一个 id 来检查观察是否已保存(附加行)。如果生成的 id 与从最后一行检索到的 id 匹配,则返回保存的 id,否则返回 0

问题:

该代码大部分时间都有效,问题是有时用户会得到 0(而不是应该返回的 id),我不确定如果附加操作似乎没有失败,为什么会这样。

我的代码:

//save observacion submitted
function saveObservation(studentICID, studentOSISICID, studentName, studentClass, dateObserv, catObsev, textObserv, textCommit){
  //return variable initialized
  var success = 0;
  //lock the app to deal with concurrency for 3 seconds
  var lock = LockService.getPublicLock();
  lock.waitLock(3000);  // wait 3 seconds before conceding defeat.
  try{
    // Log the email address of the person running the script.
    var submittedByEmail = Session.getActiveUser().getEmail().slice(0, Session.getActiveUser().getEmail().indexOf("@"));
    var now = new Date();
    //get current date/time
    var dateTime = Utilities.formatDate(now, "GMT-5", "yyyy-MM-dd' 'HH:mm:ss");
    //get the sheet to log observations
    var sODA = ssODA.getSheetByName("Observaciones");
    var rowsBeforeObservation = sODA.getLastRow();
    //get observation id
    var observID = getObservationID(studentICID, studentOSISICID);
    //log observation 
    sODA.appendRow([observID, dateTime,submittedByEmail,studentICID,studentOSISICID,studentName,studentClass,dateObserv,catObsev,textObserv,textCommit]);
    //log observation to Logger for backup
    Logger.log([
      observID, 
      dateTime,
      submittedByEmail,
      studentICID,
      studentOSISICID,
      studentName,
      studentClass,
      dateObserv,
      catObsev,
      textObserv,
      textCommit
    ]);
    //update spreadsheet
    SpreadsheetApp.flush();
    //check if observation was logged
    var lastobservIDOnSheet = sODA.getRange(sODA.getLastRow(),1,1,1).getValue();
    if(lastobservIDOnSheet == observID){
      success = observID;
    }
    Logger.log('success: ' + success);
    return success;
  }catch(e){
    //Logger.log("error in saveObservation: " + e);
    var eventcode = "saveObsFailed";
    var event = "failure";
    log_event_text(eventcode,event,e)
  }finally { //release lock
    lock.releaseLock();
  }
}

我试过的:

  1. 起初我以为我必须锁定保存操作,因为我认为这是并发问题,所以我添加了锁定部分

  2. 然后一位老师正在保存学生的观察结果并报告说它得到的是 0 而不是观察 id 所以我添加了电子表格刷新,如在这个类似的问题中所示

但同样,一位老师最近报告说得到了 0 并且日志证实了这一点(他是唯一一个使用 html 表单的人)。我不确定这个来自哪里,因为我什至自己测试过它,并且与其他用户一起工作过,也只有一个人保存,所以在这一点上我不确定我应该尝试什么或者我的锁/冲洗实施是错误的?

先感谢您。

标签: google-apps-scriptgoogle-sheets

解决方案


尝试在电子表格的写入和读取之间使用 SpreadsheetApp.flush()。

var lastobservIDOnSheet = sODA.getRange(sODA.getLastRow(),1).getValue();

问题可能是有时您没有收到 activeUsers 电子邮件

试试这种方式:

function saveObservation(studentICID, studentOSISICID, studentName, studentClass, dateObserv, catObsev, textObserv, textCommit) {
  var success = 0;
  var lock = LockService.getPublicLock();
  lock.waitLock(3000);  // wait 3 seconds before conceding defeat.
  try {
    var submittedByEmail = Session.getActiveUser().getEmail().slice(0, Session.getActiveUser().getEmail().indexOf("@"));
    if (submittedByEmail) {
      var now = new Date();
      var dateTime = Utilities.formatDate(now, "GMT-5", "yyyy-MM-dd' 'HH:mm:ss");
      var sODA = ssODA.getSheetByName("Observaciones");
      var rowsBeforeObservation = sODA.getLastRow();
      var observID = getObservationID(studentICID, studentOSISICID);
      sODA.appendRow([observID, dateTime, submittedByEmail, studentICID, studentOSISICID, studentName, studentClass, dateObserv, catObsev, textObserv, textCommit]);
    } else {
      throw "Error: Getting Active User Email";
      return 0;
    }
    SpreadsheetApp.flush();
    var lastobservIDOnSheet = sODA.getRange(sODA.getLastRow(), 1).getValue();
    if (lastobservIDOnSheet == observID) {
      success = observID;
    }
    throw "Success"
    return success;
  } catch (e) {
    throw e;
    var eventcode = "saveObsFailed";
    var event = "failure";
    log_event_text(eventcode, event, e)
  } finally { //release lock
    lock.releaseLock();
  }
}

推荐阅读