Javascript Service worker/Safari/fetch事件在消息事件之前激发
我是服务工作者的新手,我有以下情况: 下面是我的script.js中的一个块:Javascript Service worker/Safari/fetch事件在消息事件之前激发,javascript,jquery,service-worker,Javascript,Jquery,Service Worker,我是服务工作者的新手,我有以下情况: 下面是我的script.js中的一个块: if ('serviceWorker' in navigator) { if (navigator.serviceWorker.controller) { var msg = { 'form_data': params } navigator.serviceWork
if ('serviceWorker' in navigator) {
if (navigator.serviceWorker.controller) {
var msg = {
'form_data': params
}
navigator.serviceWorker.controller.postMessage(msg);
}
}
$.post(url, params, function (data) {
}).done(function(data) {
console.log('succ');
}).fail(function() {
console.log('fail');
});
下面是我的service-worker.js中的一块:
self.addEventListener('fetch', e => {
const reqClone = e.request.clone();
if (reqClone.method === 'POST') {
e.respondWith(fetch(reqClone).catch(function(error) {
savePostRequests(reqClone.url, form_data)
//Function to add requests to IndexedDB
}))
}
});
self.addEventListener('message', function (e) {
if (e.data.hasOwnProperty('form_data')) {
form_data = e.data.form_data;
}
});
而在Chrome中,消息事件在fetch事件之前触发,这意味着我在fetch中获取form_数据,而在Safari中,消息事件在fetch事件之后触发,因此我没有获取form_数据
脱机时,我需要fetch事件中的POST-call参数将它们存储在IndexedDB中
我做错了什么?有没有不同的处理方法
任何帮助都将不胜感激 您可以在service worker中拦截post请求,如果失败,则将其存储到缓存中。下面的代码应该会给你一些如何做的灵感
self.addEventListener('fetch', function(event) {
if (event.request.clone().method === 'POST') {
event.respondWith(fetch(event.request.clone(), {method:'POST'})
.catch(function(error) { // cache only if it fails(offline)
let url = event.request.clone().url;
// adjust the response to your needs
let fakeResponse = new Response(JSON.stringify({status: 'success', success:true}));
saveRequest(url, form_data); // custom function to save the request to cache
return fakeResponse.clone();
})
} else {
// handle GET requests here
}
为了获取form_数据,我使用了以下代码:
// service worker
// global variable
var form_data;
self.addEventListener('message', (event) => {
if (event.data.hasOwnProperty('form_data')) {
form_data = event.data.form_data;
}
});
我必须在我想要缓存的每个post请求中添加消息
// plain javascript
// in ajax
// normal form data used when user is online
var data = new FormData();
data.append('photo', image);
data.append('description', description);
// adjusting form data for service worker message
var object = {};
data.forEach((value, key) => {object[key] = value});
var json = JSON.stringify(object);
var msg = {
form_data: object,
}
// send form data to Service worker through post messages, works offline
swRegistration.active.postMessage(msg);
// submit the request normally.... (online only)
$.ajax({
url: ajax_url,
...
这个解决方案远非优雅,但它对我有效我已经在
Chrome
和Safari
中测试了这个示例,但我并不依赖postMessage
方法来发送表单数据
参数。相反,我依赖于ServiceWorker
侦听fetch
事件并获取处理程序内部的请求参数的能力
self.addEventListener(`fetch`,event=>{
const requestClone=event.request.clone()
事件响应(
(异步函数(){
const params=await requestClone.text().catch(err=>err)
if(参数instanceof Error){
//这是一个简单的检查,但要适当地处理错误
}
if(event.request.method==`POST`){
log(`POST request with params:${params}`)
//你在这里工作吗
}
返回获取(event.request)
})()
)
})
请注意,您必须为事件.request
创建一个克隆
,以便能够对其调用text()
方法,因为“请求是一个流,只能使用一次”,因此如果您试图获取请求的参数
,然后将其用于其他用途,则会遇到问题
此外,您可以使用以下任何方法从请求中检索正文,因此请使用适当的方法:
event.request.arrayBuffer()
event.request.blob()
event.request.json()
event.request.text()
event.request.formData()
ServiceWorker
文件中,以下示例在两种浏览器中的行为相同:
fetch(“https://jsonplaceholder.typicode.com/posts", {
方法:“张贴”,
body:JSON.stringify({title:“foo”,body:“bar”,userId:1}),
标题:{“内容类型”:`application/json`}
})
.then(response=>response.json())
.then(json=>console.log(`fetchresponse`,json))
.catch(error=>console.error(`fetcherror`,error));
//控制台日志
//>>用{“title”:“foo”,“body”:“bar”,“userId”:1}(worker.js)发布请求
//>>获取响应{title:“foo”,body:“bar”,userId:1,id:101}(index.js)
希望这能有所帮助。我对您的代码有点困惑-您是否试图在完成提取后向服务人员发送消息?您的代码中
参数在哪里?它是如何填充的?@goto1我的最终目标是将失败的POST请求(脱机)及其参数添加到IndexedDB中。params被填充(这只是我代码中的一块),我不想在我的问题中添加不相关的内容(如果你真的认为有必要,我可以添加)。那么为什么不通过SW
检查所有POST
请求,捕捉错误,抓取请求的主体,这将是你的params,然后使用它将其保存在IndexedDB
?@goto1如何获取请求的正文?这是我最初的问题。我有一个例子,当触发获取
请求时,会在ServiceWorker
中获取POST
请求的参数。它们在Chrome
和Safari
中的工作方式相同-这就是你想要的吗?它看起来与我的代码没有太大的不同。你试过在Safari上运行它吗?