Rog*_*int 8 javascript post request fetch google-cloud-functions
对于我的一生,我无法弄清楚发生了什么。我花了一整天的时间寻找答案,但在任何地方都找不到。我正在练习编写一个函数,通过电子邮件将废弃的表单发送给我。
这是我为托管表单的本地主机运行的 index.js 文件
const inputSelector = document.getElementById("name");
const fieldSelector = document.querySelectorAll('.formfield');
let formData = {};
fieldSelector.forEach(field =>{
field.addEventListener('input', (e) =>{
let formField = e.target.id;
formData[formField] = field.value;
});
})
window.addEventListener('beforeunload', () =>{
fetch('http://localhost:8080/', {
method:'post',
headers:{
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: formData
})
})
})
Run Code Online (Sandbox Code Playgroud)
请求发送到的函数是一个包含以下代码的云函数:
exports.testFetch = async (req, res) =>{
console.log(req.method);
if(req.method === 'OPTIONS'){
console.log('method is option')
res.set('Access-Control-Allow-Origin', "*")
res.set('Access-Control-Allow-Methods', 'GET, POST');
res.set('Access-Control-Allow-Headers', 'Content-Type');
}
else{
console.log('full body: ', req.body);
console.log('message: ', req.body.message);
}
res.send('response')
}
Run Code Online (Sandbox Code Playgroud)
现在,每当我填写表单字段,然后从该页面浏览到另一个页面时,它都会完美运行,云功能 console.logs 表单字段。但是,当我通过单击 X 关闭页面时,云功能仅 console.log“选项”和“方法是选项”。看起来它只发送 post 请求的选项部分。我花了整个下午寻找解决方案,但我无法在任何地方找到它。超级令人沮丧。当我将获取功能添加到按钮然后按下按钮时,它也可以完美工作。只是关闭浏览器后,它似乎不起作用并卡在选项中。如果您有任何提示,请告诉我!
War*_*zee 25
正如 Endless 的答案所讨论的,sendBeacon 是一个选项。但问题是您的获取请求没有使用keepalive 标志。
通常,当卸载文档时,所有关联的网络请求都会中止。但是 keepalive 选项告诉浏览器在后台执行请求,即使在离开页面之后也是如此。所以这个选项对于我们的请求成功至关重要。
window.addEventListener('beforeunload', () => {
fetch('http://localhost:8080/', {
method:'post',
headers:{
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: formData
}),
keepalive: true // this is important!
})
})
Run Code Online (Sandbox Code Playgroud)
它用于在卸载期间发送请求
window.addEventListener('unload', () => {
navigator.sendBeacon(url, data)
})
Run Code Online (Sandbox Code Playgroud)
旁注:我建议使用FormData来序列化您的数据。你可以发送它而不是一些 json。但必须使用 name 属性而不是 id。无论哪种方式你都应该这样做。
var fd = new FormData(formElement)
// if you want json anyway
var json = JSON.stringify(Object.fromEntries(fd))
Run Code Online (Sandbox Code Playgroud)
我会删除fieldSelector.forEach(...
并在卸载事件时构建一次表单数据
由于您无法使用 sendBeacon 指定任何标头,因此您可以发送 Blob
var blob = new Blob([json], {type: 'application/json')
navigator.sendBeacon(url, blob)
Run Code Online (Sandbox Code Playgroud)
更多信息在这里/sf/answers/2921076791/
如果这对您不起作用,请尝试在 fetch 中使用保持活动标志{ keepalive: true }