javascript - 使用 Javascript 中的 Fetch 在 JSON 中搜索值
问题描述
我正在 VS Code 中使用用于客户数据的 html 表单制作应用程序。由于我们公司的设置,我必须将数据存储在 Google 表格中。经过大量搜索后,我在 YouTube 上找到了一系列很棒的教程,向我展示了如何通过将数据发布为应用程序脚本 Web 应用程序来访问 JSON 格式的数据,然后使用 fetch 获取数据。
但是,我对所有这一切都非常陌生,而我没有学到的一件事,并且在试图找到(即使在这个网站上)时遇到了很多麻烦,就是如何搜索数据以查看是否值已存在于谷歌表中。我不想在工作表中创建重复的客户。我希望有人可以告诉我如何通过 fetch 搜索 JSON 数据,以在变量或更好的方法中获取 true 或 false,对于单个键值以及一组对(多个键对)。例如,假设我正在尝试使电话 # 成为唯一键,并且我希望能够搜索那个或带有姓氏的电话 #。然后,如果值已经存在,或者它/它们不存在,我可以继续创建适当的行为。
这是我的 HTML 的样子:
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
<title>Add a Customer</title>
</head>
<body>
<div class="container">
<h1>Add a Customer</h1>
<form id="customerForm" novalidate>
<div class="row p-2">
<div class="col">
<input type="text" class="form-control" placeholder="First name" aria-label="First name" id="firstName" required minlength="2">
<div id="validationServer05Feedback" class="invalid-feedback">
Please provide a valid First Name.
</div>
</div>
<div class="col">
<input type="text" class="form-control" placeholder="Last name" aria-label="Last name" id="lastName" required minlength="3">
<div id="validationServer05Feedback" class="invalid-feedback">
Please provide a valid Last Name.
</div>
</div>
</div>
<div class="row p-2">
<div class="col">
<input type="text" class="form-control" placeholder="Telephone" aria-label="Telephone" id="telephone">
</div>
<div class="col">
<input type="text" class="form-control" placeholder="City" aria-label="City" id="city">
</div>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary" type="button" id="submitButton">
<span id="buttonSpinner" class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
<span id="buttonText">Send</span>
</button>
<div class="alert alert-danger mt-2 d-none" role="alert" id="unknownError">
Something Went Horribly Wrong!
</div>
</div>
</form>
</div>
<!-- Optional JavaScript; choose one of the two! -->
<!-- Option 1: Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js" integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script>
<!-- Option 2: Separate Popper and Bootstrap JS -->
<!--
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.1/dist/umd/popper.min.js" integrity="sha384-SR1sx49pcuLnqZUnnPwx6FCym0wLsk5JZuNx2bPPENzswTNFaQU1RDvt3wT4gWFG" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.min.js" integrity="sha384-j0CNLUeiqtyaRmlzUHCPZ+Gy5fQu0dQ6eZ/xAww941Ai1SxSY+0EQqNXNE6DZiVc" crossorigin="anonymous"></script>
-->
<script src="customers.js"></script>
</body>
</html>
和客户端 JavaScript:
var customerForm = document.getElementById("customerForm");
var firstName = document.getElementById("firstName");
var lastName = document.getElementById("lastName");
var telephone = document.getElementById("telephone");
var city = document.getElementById("city");
var submitButton = document.getElementById("submitButton");
var buttonSpinner = document.getElementById("buttonSpinner");
var buttonText = document.getElementById("buttonText");
var unknownError = document.getElementById("unknownError");
function afterSubmit(e){
e.preventDefault();
if (customerForm.checkValidity() === false) {
e.stopPropagation();
for(field of customerForm.elements) {
if(!field.checkValidity()){
field.classList.add("is-invalid");
}
}
return;
}
// customerForm.classList.add('was-validated')
for(field of customerForm.elements) {
field.classList.remove("is-invalid");
}
var info = {
first: firstName.value,
last: lastName.value,
telephone: telephone.value,
city: city.value,
};
var url = "https://script.google.com/macros/s/AKfycbyWBN9OE7USFtzweft6V7XvS2nD8fDsyuCDb0pN_jGApUFr_UUsXBG1SQ-oU0OT8Ep6/exec";
buttonText.textContent = "Sending...";
buttonSpinner.classList.remove("d-none");
submitButton.disabled = true;
fetch(url,{
method: 'POST',
cache: 'no-cache',
redirect: 'follow',
body: JSON.stringify(info)
})
.then(res => res.json())
.then(res => {
console.log(res);
customerForm.reset();
buttonText.textContent = "Send";
buttonSpinner.classList.add("d-none");
submitButton.disabled = false;
})
.catch(err => {
console.log(err);
console.log("Something went wrong");
unknownError.classList.remove("d-none");
setTimeout(function(){
unknownError.classList.add("d-none");
buttonText.textContent = "Send";
buttonSpinner.classList.add("d-none");
submitButton.disabled = false;
},3000);
});
}
customerForm.addEventListener("submit",afterSubmit);
和 Apps 脚本 JavaScript:
function doGet(e) {
const limit = e.parameter.limit === "undefined" ? null : e.parameter.limit;
const limitNumber = /^[1-9]\d*$/.test(limit) ? parseInt(limit) : null;
const offset = e.parameter.offset === "undefined" ? null : e.parameter.offset;
const offsetNumber = /^[1-9]\d*$/.test(offset) ? parseInt(offset) : null;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("customers");
let data = ws.getRange("A1").getDataRegion().getValues();
const headers = data.shift();
const jsonArray = data.map(r => {
let obj = {};
headers.forEach((h,i) => {
obj[h] = r[i];
});
return obj;
});
const response = [{status: 200,data: jsonArray}];
return sendJSON_(response);
}
function doPost(e){
const requiredColumns = ["first","last"];
let jsonResponse;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("customers");
const headers = ws.getRange(1,1,1,ws.getLastColumn()).getValues()[0];
const headersOriginalOrder = headers.slice();
headersOriginalOrder.shift();
headers.shift();
headers.sort();
const body = e.postData.contents;
const bodyJSON = JSON.parse(body);
const headersPassed = Object.keys(bodyJSON).sort();
if(!checkColumnsPassed_(headers,headersPassed,requiredColumns)){
throw new Error("Something went wrong");
return;
}
const arrayofData = headersOriginalOrder.map(h => bodyJSON[h]);
const aoaIds = ws.getRange(2,1,ws.getLastRow()-1,1).getValues();
const newIDNumber = getMaxFromArrayOfArray_(aoaIds) +1;
arrayofData.unshift(newIDNumber);
ws.appendRow(arrayofData);
bodyJSON.id = newIDNumber;
return sendJSON_(bodyJSON);
}
function checkColumnsPassed_(arrAllColumns,arrColumnsPassed,arrRequiredColumns){
if(!arrRequiredColumns.every(item => arrColumnsPassed.includes(item))) return false;
if(!arrColumnsPassed.every(item => arrAllColumns.includes(item))) return false;
return true;
}
function sendJSON_(jsonResponse){
return ContentService
.createTextOutput(JSON.stringify(jsonResponse))
.setMimeType(ContentService.MimeType.JSON);
}
//return the highest number / id
function getMaxFromArrayOfArray_(aoa){
let maxID = 0;
aoa.forEach(r => {
if(r[0] > maxID) maxID = r[0];
});
return maxID;
}
抱歉,如果代码太多,但我想提供我正在使用的所有东西,以防我需要注意一些事情。如果我需要澄清我的问题,请告诉我。
提前感谢您提供的任何帮助!
解决方案
我相信你的目标如下。
- 提交 HTML 表单时,您要检查输入的电话号码和姓氏是否存在于电子表格的“客户”表中。
- 当电子表格的“客户”表中不存在输入的电话号码和姓氏时,您要添加它。
- 当输入的电话号码和姓氏存在于电子表格的“客户”表中时,您不想添加它。
在这种情况下,如何修改doPost
您的 Google Apps Script 的功能如下?
从:
if(!checkColumnsPassed_(headers,headersPassed,requiredColumns)){
throw new Error("Something went wrong");
return;
}
const arrayofData = headersOriginalOrder.map(h => bodyJSON[h]);
至:
if (!checkColumnsPassed_(headers, headersPassed, requiredColumns)) {
throw new Error("Something went wrong");
return;
}
// --- I added below script.
const checkHeaders = ["telephone", "last"];
const [, ...v] = ws.getDataRange().getValues();
const headerObj = headers.reduce((o, f, i) => Object.assign(o, {[f]: i}), {});
const duplicateCheck = v.some(r => checkHeaders.every(h => r[headerObj[h]] == bodyJSON[h]));
if (duplicateCheck) return sendJSON_({duplicated: true});
// ---
const arrayofData = headersOriginalOrder.map(h => bodyJSON[h]);
- 通过上述修改,当“客户”表中存在
telephone
和的值时,返回,输入的值不相加,返回。last
duplicateCheck
true
{duplicated: true}
- 另一方面,当 和 的值
telephone
在last
“客户”表中不存在时,duplicateCheck
返回false
并添加输入的值。
笔记:
当您修改 Google Apps Script for Web Apps 时,请将部署修改为新版本。通过这种方式,修改后的脚本会在不更改 Web 应用程序的 URL 的情况下反映到 Web 应用程序。请注意这一点。
- 您可以在“在不更改新 IDE 的 Web 应用程序 URL 的情况下重新部署 Web 应用程序”的报告中查看详细信息。
在此修改中,我不确定标头值。所以在搜索值之前,每个标题值的列索引被检索为
headerObj
.
参考:
推荐阅读
- mysql - 根据同一记录的其他字段中的值更新记录的字段
- ansible - Ansible:将字典转换为名称=值字符串
- python - 使覆盖仅计算成功的测试并忽略 xfailing 测试
- java - Google pubsub 异步 java API 干净关闭
- go - 如何使用 golang 更新 .yaml 文件中键的值?
- javascript - 如何将 joomla 表单(在文章中)重定向到不同的 joomla 文章?
- java - 尝试从 java 运行 jar 时无法获取控制台实例
- c - 什么是 typdef size_t 实际代码定义
- java - 使用证书 .p12 签署包 .deb
- entity-framework - 使用实体框架从 MSSQL 返回一组非常具体的数据