Google sheets API gives Uncaught (in promise) TypeError: NetworkError when attempting to fetch resource
Google sheets API gives Uncaught (in promise) TypeError: NetworkError when attempting to fetch resource
我正在尝试连接一个非常基本的网络,只有 HTML/CSS/JS,google sheet。当我提交表单以将数据上传到 sheet 时,我得到:
Uncaught (in promise) TypeError: NetworkError when attempting to fetch
resource.
我一直在阅读这是因为 CORS,但我不知道如何解决它。我的代码非常简单,在 google 脚本中:
function doPost(e){
let jsonResponse;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName('web')
const headers = ws.getRange(1, 1, 1, ws.getLastColumn()).getValues()[0];
const body = e.postData.contents;
const bodyJSON = JSON.parse(body);
jsonResponse = ws.appendRow([bodyJSON.name, bodyJSON.email])
return sendJSON_(jsonResponse)
}
function sendJSON_(jsonResponse) {
return ContentService.createTextOutput(JSON.stringify(jsonResponse)).setMimeType(ContentService.MimeType.JSON);
}
我已将我的 HTML 的代码减少到最少及其:
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id='form' class="form">
<form id="customerForm">
<input type="text" id="name" placeholder="name">
<input type="email" id="email" placeholder="Email">
<button type="submit" id="submitButton">Send</button>
</form>
<script>
function afterSubmit(e){
url = 'https://script.google.com/macros/s/........../exec'
var name = document.getElementById('name')
var email = document.getElementById('email')
var info = {
name: name.value,
email: email.value
};
console.log(info);
fetch(url, {
method: 'POST',
cache: 'no-cache',
redirect: 'follow',
body: JSON.stringify(info)
})
.then(res => res.json())
.then(res => {
console.log(res)
})
}
document.getElementById('customerForm').addEventListener('submit', afterSubmit);
</script>
</body>
</html>
我还检查过,当我将 google sheets 脚本发布为网络应用程序时,我将选项正确设置为:
以以下身份执行应用程序:我 (email@gmail.com)
谁有权访问该应用程序:任何人,甚至是匿名的
我在控制台中得到错误的方法是简单地用浏览器打开 HTML 文件,填写数据并按发送。
修改后的 Apps 脚本
function doPost(e){
let jsonResponse;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName('web')
const headers = ws.getRange(1, 1, 1, ws.getLastColumn()).getValues()[0];
const body = e.postData.contents;
const bodyJSON = JSON.parse(body);
jsonResponse = {"name": bodyJSON.name, "email": bodyJSON.email} // MODIFIED
ws.appendRow([jsonResponse.name, jsonResponse.email]) // MODIFIED
}
我认为您的主要问题出在这一行
jsonResponse = ws.appendRow([bodyJSON.name, bodyJSON.email])
如果您看到 appendRow
method,它表示 return 类型是 Sheet
。所以理论上,没有我的修改,下一行应该return报错了。 Apps 脚本仪表板中的执行说明了什么?也就是说,它可能仍然能够更新 sheet.
通过此修改,您的 HTML 成功更新了脚本,即使它在浏览器控制台中引发了一堆错误。
你不需要明确地 return 任何东西就可以运行,这就是我在这里省略它的原因。
已修改HTML
function afterSubmit(e) {
url =
"https://script.google.com/macros/s/<SCRIPT_ID>/exec";
var name = document.getElementById("name");
var email = document.getElementById("email");
var info = {
name: name.value,
email: email.value,
};
console.log(info);
fetch(url, {
method: "POST",
cache: "no-cache",
mode: "no-cors", // to prevent CORS errors
redirect: "follow",
body: JSON.stringify(info),
})
.then((res) => console.log(res))
.catch((err) => console.log(err));
e.preventDefault(); // to prevent form from reloading page
}
document.getElementById("customerForm").addEventListener("submit", afterSubmit);
- 这里唯一添加的是
mode: "no-cors"
。
- 最后的
e.preventDefault()
抑制了我收到的“无法获取”错误,因为表单提交会自动重新加载页面。似乎由于页面重新加载发生在响应返回之前,它只会说“失败”,尽管它已成功更新脚本。
- 由于 no-cors 参数,returned 对象实际上是空白的,请参阅 response type。
如果您想要更有意义的回复,@Tanaike 在之前的帖子中建议使用异步,如下所示:
const fetchData = async (url, info) => {
var json;
try {
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(info),
});
if (response != "") json = await response.json();
console.log('Success:', JSON.stringify(json));
} catch (e) {
console.log('Errors:', e.message)
}
return json;
}
async function main() {
const res = await fetchData(url, info);
console.log(res);
}
main()
这还需要将其添加到 Apps 脚本端:
return ContentService.createTextOutput(JSON.stringify(e)).setMimeType(ContentService.MimeType.JSON);
参考资料
我正在尝试连接一个非常基本的网络,只有 HTML/CSS/JS,google sheet。当我提交表单以将数据上传到 sheet 时,我得到:
Uncaught (in promise) TypeError: NetworkError when attempting to fetch resource.
我一直在阅读这是因为 CORS,但我不知道如何解决它。我的代码非常简单,在 google 脚本中:
function doPost(e){
let jsonResponse;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName('web')
const headers = ws.getRange(1, 1, 1, ws.getLastColumn()).getValues()[0];
const body = e.postData.contents;
const bodyJSON = JSON.parse(body);
jsonResponse = ws.appendRow([bodyJSON.name, bodyJSON.email])
return sendJSON_(jsonResponse)
}
function sendJSON_(jsonResponse) {
return ContentService.createTextOutput(JSON.stringify(jsonResponse)).setMimeType(ContentService.MimeType.JSON);
}
我已将我的 HTML 的代码减少到最少及其:
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id='form' class="form">
<form id="customerForm">
<input type="text" id="name" placeholder="name">
<input type="email" id="email" placeholder="Email">
<button type="submit" id="submitButton">Send</button>
</form>
<script>
function afterSubmit(e){
url = 'https://script.google.com/macros/s/........../exec'
var name = document.getElementById('name')
var email = document.getElementById('email')
var info = {
name: name.value,
email: email.value
};
console.log(info);
fetch(url, {
method: 'POST',
cache: 'no-cache',
redirect: 'follow',
body: JSON.stringify(info)
})
.then(res => res.json())
.then(res => {
console.log(res)
})
}
document.getElementById('customerForm').addEventListener('submit', afterSubmit);
</script>
</body>
</html>
我还检查过,当我将 google sheets 脚本发布为网络应用程序时,我将选项正确设置为: 以以下身份执行应用程序:我 (email@gmail.com) 谁有权访问该应用程序:任何人,甚至是匿名的
我在控制台中得到错误的方法是简单地用浏览器打开 HTML 文件,填写数据并按发送。
修改后的 Apps 脚本
function doPost(e){
let jsonResponse;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName('web')
const headers = ws.getRange(1, 1, 1, ws.getLastColumn()).getValues()[0];
const body = e.postData.contents;
const bodyJSON = JSON.parse(body);
jsonResponse = {"name": bodyJSON.name, "email": bodyJSON.email} // MODIFIED
ws.appendRow([jsonResponse.name, jsonResponse.email]) // MODIFIED
}
我认为您的主要问题出在这一行
jsonResponse = ws.appendRow([bodyJSON.name, bodyJSON.email])
如果您看到
appendRow
method,它表示 return 类型是Sheet
。所以理论上,没有我的修改,下一行应该return报错了。 Apps 脚本仪表板中的执行说明了什么?也就是说,它可能仍然能够更新 sheet.通过此修改,您的 HTML 成功更新了脚本,即使它在浏览器控制台中引发了一堆错误。
你不需要明确地 return 任何东西就可以运行,这就是我在这里省略它的原因。
已修改HTML
function afterSubmit(e) {
url =
"https://script.google.com/macros/s/<SCRIPT_ID>/exec";
var name = document.getElementById("name");
var email = document.getElementById("email");
var info = {
name: name.value,
email: email.value,
};
console.log(info);
fetch(url, {
method: "POST",
cache: "no-cache",
mode: "no-cors", // to prevent CORS errors
redirect: "follow",
body: JSON.stringify(info),
})
.then((res) => console.log(res))
.catch((err) => console.log(err));
e.preventDefault(); // to prevent form from reloading page
}
document.getElementById("customerForm").addEventListener("submit", afterSubmit);
- 这里唯一添加的是
mode: "no-cors"
。 - 最后的
e.preventDefault()
抑制了我收到的“无法获取”错误,因为表单提交会自动重新加载页面。似乎由于页面重新加载发生在响应返回之前,它只会说“失败”,尽管它已成功更新脚本。 - 由于 no-cors 参数,returned 对象实际上是空白的,请参阅 response type。
如果您想要更有意义的回复,@Tanaike 在之前的帖子中建议使用异步,如下所示:
const fetchData = async (url, info) => {
var json;
try {
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(info),
});
if (response != "") json = await response.json();
console.log('Success:', JSON.stringify(json));
} catch (e) {
console.log('Errors:', e.message)
}
return json;
}
async function main() {
const res = await fetchData(url, info);
console.log(res);
}
main()
这还需要将其添加到 Apps 脚本端:
return ContentService.createTextOutput(JSON.stringify(e)).setMimeType(ContentService.MimeType.JSON);