html - 通过 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;
}
解决方案
问题:
如果我理解正确,您希望避免在服务器端函数尚未返回数据keydown
时执行事件。keyPressFunction
searchData
解决方案:
如果是这种情况,我建议您在开始时使用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);
}
更新:
keyPressFunction
searchData
如果按下的键不是 ,则在不调用服务器函数的情况下完成执行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
因此,如果您希望它运行,请将其移至上述行的顶部(以 开头)。
参考:
推荐阅读
- python - 将python文件转换为exe时有没有办法最小化命令提示符
- react-native - 为什么 React Native aspectRatio 在视频元素上被忽略?
- flutter - 用于实现这种布局的最佳颤振小部件是什么?
- javascript - Keydown 事件在 Javascript 中不起作用
- ansible - 如何告诉 Ansible 在任务中包含本地主机
- leaflet - 传单画布标记无法设置笔划
- javascript - 循环一个开关盒的随机数最多 n 次
- java - 批量更新弹性搜索实体
- javascript - 想要在 jQuery 中单击按钮时停止功能
- c# - 任务应如何正确发出 Windows 服务关闭的信号?