首页 > 解决方案 > 通过 withSuccessHandler 和 onSuccess 在来自 html 输入的请求之间设置一个计时器

问题描述

我在html页面中有问题。

用户在 html 输入中输入数据并单击输入。在此之后,它必须开始通过函数“keyPressFunction” throw withSuccessHandler(onSuccess) 检查电子表格上 3 个表中的 Google-apps 脚本函数“searchData”,结果必须以 true/false 返回到 var“findData”。如果为真,则焦点转到下一个输入。第三次输入后数据写入表。

但是来自apps-script的回答缓慢返回,接近5秒,但焦点已经熄灭,此时数据确实不正确。你能帮我在请求之间设置这个计时器吗?

为了理解测试项目在这里https://docs.google.com/spreadsheets/d/1FqUmJcTipwKX9Q5m-4dlmXIChp5k1Z98xR2m42GpIT0/edit#gid=0

最后部署的网络应用程序链接在这里https://script.google.com/a/fmlogistic.com/macros/s/AKfycbwAcfIVGrbcu24t_6OxtR2gvltG3ojbh1_pNxLed1O8/dev

<script>

  const inputs = document.querySelector('.dws-input');
  const formControl = document.querySelectorAll('.form-control');

  let findData;
  let curInpID;
  let firstValid, secValid, thirdValid, allValid;

  formControl[0].focus();

  function keyPressFunction(ev) {

    let userInfo = {};
    userInfo.login = document.getElementById("tLogin").value;
    userInfo.table = document.getElementById("tTable").value;
    userInfo.order = document.getElementById("tOrder").value;

    let inputData = ev.target.value
    let btnReset = document.getElementById("del");

    if (ev.code !== 'Enter') return;
    if (ev.target.classList.contains("is-valid")) ev.target.classList.remove("is-valid");
    if (ev.target.classList.contains("is-invalid")) ev.target.classList.remove("is-invalid");

    curInpID = ev.target.id;
   
google.script.run.withSuccessHandler(onSuccess).searchData(inputData, curInpID);
//the true/false returns here in findData: 

    console.log(findData);

    if (!findData) {   
      ev.target.classList.add("is-invalid");
      ev.target.focus();
      return;
    } else {
      ev.target.classList.add("is-valid");
    };

    btnReset.disabled = (!firstValid == true);

    allValid = (firstValid == true && secValid == true && thirdValid == true) ? true : false;

    for (const i of formControl) {
      if (i.value === '') {
        i.nextElementSibling.focus();
        break;
      }
    }
    
    if (allValid){
      google.script.run.userClicked(userInfo);
      document.getElementById("tTable").value = '';
      document.getElementById("tOrder").value = '';
      secValid = false;
      thirdValid = false;
      document.getElementById("tTable").focus();
    }
  }

  function onSuccess(_findData) {
    findData = _findData;
    if (!firstValid) firstValid = (findData && curInpID == "tLogin") ? true : false;
    if (!secValid) secValid = (findData && firstValid && curInpID == "tTable") ? true : false;
    if (!thirdValid) thirdValid = (findData && firstValid && secValid && curInpID == "tOrder") ? true : false;
    allValid = (firstValid && secValid && thirdValid) ? true : false;
  }
  
  inputs.addEventListener('keydown', keyPressFunction);

</script>
<!doctype html>
<html lang="en">
<head>
<title>CLR: PACKING</title>
<meta charset = "UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet"
       integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
    <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <link rel="stylesheet" href="/resources/demos/style.css">
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>      
</head>
<body>
    <div class="conteiner">
        <form novalidate>
            <h6 class="title">PACKING</h6>
            <div class="dws-input">
                <div class="col-md-3"></div>
                <div>
                    <div class="form-floating mb-3 mt-3">
                        <input type="text" class="form-control" novalidate id="tLogin" name= "username" placeholder= "Login:" autofocus > 
                        <label for="tLogin">Login:</label>
                    </div>
                    <div class="form-floating mb-3 mt-3">
                        <input type="text" class="form-control"  novalidate id="tTable" name= "text" placeholder= "Table:" >
                        <label for="tTable">Table:</label>
                    </div>
                </div>
                <div class="form-floating mb-3 mt-3">
                    <input type="text"  novalidate class="form-control" id="tOrder" name= "text" placeholder= "Order:" >
                    <label for="tOrder">Order:</label>
                </div> 
            </div>  
        </form>
    </div>
    
    <?!= include("index-js"); ?>

</body>



</html>

在 Apps 脚本我有下一个脚本:

const url = SpreadsheetApp.getActiveSpreadsheet().getUrl();
  let ss = SpreadsheetApp.openByUrl(url);
  let sheetTo = ss.getSheetByName("@sistem");
  let sheetIn = ss.getSheetByName("@packing");
  
function doGet(e){

    var htmlServ = HtmlService.createTemplateFromFile("index");
    return htmlServ.evaluate();

}

function userClicked(userInfo){

  sheetIn.appendRow([userInfo.login, userInfo.table, userInfo.order, new Date()]);
  Logger.login(userInfo.name + "clicked the button");
}

function include(filename){
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

function searchData(inputData, curInpID){

  var result;
  
  var lrLogins = sheetTo.getRange("A:A").getValues().filter(String).length;
  var arrLogins = sheetTo.getRange(1, 1, lrLogins, 1).getValues().flat();
  
  var lrTMPLORDS = sheetTo.getRange("K:K").getValues().filter(String).length;
  var curTMPLORDS = sheetTo.getRange(1, 11, lrTMPLORDS, 1).getValues();
  
  var lrTABLES = sheetTo.getRange("R:R").getValues().filter(String).length;
  var curTABLES = sheetTo.getRange(1, 18, lrTABLES, 1).getValues().flat();

  if (curInpID == "tLogin"){
    result = (arrLogins.indexOf(inputData) !== -1) ? true : false;
  }
  else if (curInpID == "tTable"){
    result = (curTABLES.indexOf(inputData) !== -1) ? true : false;
  }  
  else if (curInpID == "tOrder"){
    for (i = 0 ; i < curTMPLORDS.length; i ++){
      var regexstring = curTMPLORDS[i];
      var regexp = new RegExp(regexstring, "i");
      var result = regexp.test(inputData);
      if (result) break;
    }
  }
    return result;
  }

标签: htmlgoogle-apps-script

解决方案


问题:

如果我理解正确,您希望避免在服务器端函数尚未返回数据keydown时执行事件。keyPressFunctionsearchData

解决方案:

如果是这种情况,我建议您在开始时使用removeEventListenerkeyPressFunction(以避免连续keydown事件触发此函数的更多执行),并在执行成功处理函数时通过addEventListeneronSuccess再次添加它( )。

它可能是以下几行:

function keyPressFunction(ev) {
  inputs.removeEventListener('keydown', keyPressFunction);
  // ... REST OF YOUR FUNCTION
}

function onSuccess(_findData) {
  // ... REST OF YOUR FUNCTION
  inputs.addEventListener('keydown', keyPressFunction);
}

更新:

keyPressFunctionsearchData如果按下的键不是 ,则在不调用服务器函数的情况下完成执行Enter。由于事件只有在searchData返回并onSuccess运行后才会重新激活,所以如果按下的键不是 ,则不会重新激活Enter。因此,keyPressFunction只会运行一次(如果按下的键不是Enter)。

为了避免这种情况,请removeEventListener在调用之前将该行移至searchData

function keyPressFunction(ev) {
  // ... REST OF YOUR FUNCTION
  inputs.removeEventListener('keydown', keyPressFunction);
  google.script.run.withSuccessHandler(onSuccess).searchData(inputData, curInpID);
}

旁注:请注意,keyPressFunction调用后写入的所有内容searchData将永远不会执行,因为执行将移至失败或成功处理程序(onSuccess在您的情况下)。google.script.run因此,如果您希望它运行,请将其移至上述行的顶部(以 开头)。

参考:


推荐阅读