Name with gear icon in Chrome network requests table - google-chrome-devtools

(30119999.xml in pic1, has a gear mark pre name)
I set this request in Web Worker, response data is ok and I terminated it in onmessage callback
but why the request always in pending and can't preview, please help.
pseudocode:
const workerBlob = new Blob([`onmessage = function (event) {
const xhr = new XMLHttpRequest();
xhr.addEventListener('load', function () {
postMessage(xhr.response);
});
xhr.open('GET', event.data.url, true);
xhr.send();
}`], { type: 'application/javascript' });
const workerURL = URL.createObjectURL(workerBlob);
const worker = new Worker(workerUrl);
worker.postMessage({url});
worker.onmessage = (message) => {
// do something
worker.terminate();
};

According to Debugging Service Workers :
The gear icon signifies that these requests came from the Service
Worker itself. Specifically, these are the requests being made by the
Service Worker's install handler to populate the offline cache.

Make sure you are not terminating your worker too fast. You should terminate the Worker when the loadend event has fired.

Related

Service workers "sync" operation is working while its offline?

I have a PWA project where I send the data to server. During this process, if the user is offline then the data is stored in indexedDb and a sync tag is registered. So, then when the user comes online that data can sent to the server.
But In my case the sync event gets executed immediately when the we register a sync event tag, which means the data is tried to be sent to server while its offline, which is not going to work.
I think the sync event supposed to fire while its online only, what could be issue here ?
The service worker's sync event works accordingly when I tried to enable and disable the offline option of chrome devtools, and also works correctly in my android phone.
This is how I register my sync tag
function onFailure() {
var form = document.querySelector("form");
//Register the sync on post form error
if ('serviceWorker' in navigator && 'SyncManager' in window) {
navigator.serviceWorker.ready
.then(function (sw) {
var post = {
datetime1: form.datetime1.value,
datetime: form.datetime.value,
name: form.name.value,
image: form.url.value,
message: form.comment.value
};
writeData('sync-comments', post)
.then(function () {
return sw.sync.register('sync-new-comment');
})
.then(function () {
console.log("[Sync tag registered]");
})
.catch(function (err) {
console.log(err);
});
});
}
}
And this is how the sync event is called
self.addEventListener('sync', function (event) {
console.log("[Service worker] Sync new comment", event);
if (event.tag === 'sync-new-comment') {
event.waitUntil(
readAllData('sync-comments')
.then(function (data) {
setTimeout(() => {
data.forEach(async (dt) => {
const url = "/api/post_data/post_new_comment";
const parameters = {
method: 'POST',
headers: {
'Content-Type': "application/json",
'Accept': 'application/json'
},
body: JSON.stringify({
datetime: dt.datetime,
name: dt.name,
url: dt.image,
comment: dt.message,
datetime1: dt.datetime1,
})
};
fetch(url, parameters)
.then((res) => {
return res.json();
})
.then(response => {
if (response && response.datetimeid) deleteItemFromData('sync-comments', response.datetimeid);
}).catch((error) => {
console.log('[error post message]', error.message);
})
})
}, 5000);
})
);
}
});
you mention
The service worker's sync event works accordingly when I tried to enable and disable the offline option of chrome devtools, and also works correctly in my android phone.
So I'm not sure which case is the one failing.
You are right that the sync will be triggered when the browser thinks the user is online, if the browser detects that the user is online at the time of the sync registration it will trigger the sync:
In true extensible web style, this is a low level feature that gives you the freedom to do what you need. You ask for an event to be fired when the user has connectivity, which is immediate if the user already has connectivity. Then, you listen for that event and do whatever you need to do.
Also, from the workbox documentation
Browsers that support the BackgroundSync API will automatically replay failed requests on your behalf at an interval managed by the browser, likely using exponential backoff between replay attempts.

Why does pusher in a service worker disconnect every minute?

my website refreshs let's say every 5 minutes and I use a service worker. Inside this service worker I use pusher.com and this happens:
There are many "Connection" and "Disconnection" events for only two Clients (Raspberry Pi). After this "Vacated" event there is no re-subscription.
Here is what every site does:
if ('serviceWorker' in navigator) { // Make sure sw are supported
window.addEventListener('load', () => {
navigator.serviceWorker
.register('/sw.js')
.then(reg => {
console.log('Service Worker: Registered');
})
.catch(err => console.log(`Service Worker: Error: ${err}`));
});
}
And this happens only once (and not on activating) in service worker:
var channel = pusher.subscribe('web-' + channel);
const swListener = new BroadcastChannel('swListener');
channel.bind('foo', function() {
self.foo();
});
If I run this code above on every page request everything get worse.
Did I something wrong? Is there a way to check my actual subscriptions in my service worker?

Why is the web worker api not working in react even in the simplest implementation?

I created a toy mern app which can upload images to mongodb. It works fine in the development but after I deploy to heroku, I get a timeout error. After doing a fair amount of investigations I come to the conclusion that web workers will help sort this out. So I've done this:
This is a snippet from the component that takes care of sending this request, to upload an image:
const handleUploadPhoto = evt => {
evt.preventDefault();
const worker = new Worker('imageUpload.js');
worker.postMessage(selectedPhotos);
worker.onmessage = evt => console.log(evt.data);
closeModal();
};
This whole component is actually a modal, and after I submit this handleUploadPhoto function the modal closes. Notice the closeModal function;
In the same folder as this component I have the imageUpload.js worker file:
self.addEventListener('message', evt => {
const { selectedPhotos } = evt.data;
selectedPhotos.map(photo => {
const formData = new FormData();
formData.append('photo', photo);
fetch( `/api/photo/upload/${JSON.parse(localStorage.getItem('loggedUser'))._id}`, {
method: 'POST',
body: formData,
headers: ['Content-Type', 'multipart/form-data'],
}).then(() => console.log('OK'));
});
self.postMessage(evt.data);
});
The idea behind this functionality is that I select one or more images, then I map through them and send a post request to the server with each image as formData. So I thought to move the request to a worker so that it doesn't break my UI anymore. Needless to say that it doesn't work and it gives net::EMPTY_RESPONSE error after some seconds. What I also noticed is that the worker doesn't communicate with the file it was issued in at all. I tried to make a text message pop in the console:
const handleUploadPhoto = evt => {
evt.preventDefault();
const worker = new Worker('imageUpload.js');
worker.postMessage('Hello');
worker.onmessage = evt => console.log(evt.data);
closeModal();
};
In the same folder as this component I have the imageUpload.js worker file:
self.addEventListener('message', evt => {
self.postMessage(evt.data + ' world');
});
It doesn't work. I tried the same approach in a separate project and it worked.
How can I make an HTTP request do what it's supposed to do from a web worker?

I'm getting a Web Push Error Code Status 403, which is driving me nuts, because its telling me to use firebase. What's going on?

I keep getting a WebPush Error (Status Code 403) fro Chrome for a PWA I'm building and the body says that I need to use the VAPID server key from the 'firebase console' but I used nodes Web-Push library to generate the VAPID Keys, whats going on? Do I have to use firebase to build PWAs in Chrome?
Here's the Error Message I'm getting from the browser when I send a push notification:
name: 'WebPushError',
message: 'Received unexpected response code',
statusCode: 403,
headers:
{ 'content-type': 'text/plain; charset=utf-8',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '0',
date: 'Thu, 31 Oct 2019 19:59:02 GMT',
'content-length': '194',
'alt-svc':
'quic=":443"; ma=2592000; v="46,43",h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000',
connection: 'close' },
body:
'the key in the authorization header does not correspond to the sender ID used to subscribe this user. Please ensure
you are using the correct sender ID and server Key from the Firebase console.\n',
endpoint:
'https://fcm.googleapis.com/fcm/send/exXmW3OFOTY:APA91bEKW_vxnvOZohog34pprDH6XvBsxtfnUpBdYY7z_7q4GZGa4wrmtBBg4kTRwLtgy3lNpCs8SMlvOr4nY-Fu_4zUus6zEJh69581Ier14QZxkEEVXyZHKRaZcmHa3zmbZRB4VD7Z
and here's the code that is running my node server:
//Handle imports
const express = require('express')
const cors = require('cors')
const bodyParser = require('body-parser')
const webPush = require('web-push')
const vapidKeys = require('./vapid.json')
const path = require('path')
//Setup application
const app = express()
app.use(cors())
app.use(bodyParser.json())
app.use('/static', express.static(path.join(__dirname,'frontend')))
const port = 8080
//Set up webpush
webPush.setVapidDetails(
'mailto: <email>',
vapidKeys.publicKey,
vapidKeys.privateKey
)
const pushOptions = {
proxy: '<proxy>'
}
//setup Push Notification
const sendNotification = (subscription, dataToSend='') => {
webPush.sendNotification(subscription, dataToSend, pushOptions).catch(error => { console.log('Damn it: ', error.message, '||', error)
})
}
//Server Routes Defined
app.get('/', (req, res) => res.sendFile('index.html', { root: './' }))
//Setup Database Methods
const dummyDb = {subscription: null}
const saveToDatabase = async subscription => {
dummyDb.subscription = subscription
}
//Other Server Routes
app.post('/save-subscription', async (req, res) => {
const subscription = req.body
await saveToDatabase(subscription)
console.log('subscribed!')
res.json({message: 'success'})
})
app.get('/send-notification', (req, res) => {
const subscription = dummyDb.subscription
const message = 'hello world'
sendNotification(subscription, message)
res.json({message: dummyDb.subscription})
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
I have node.js express, postgres, angular 8 app.
I had the same problem and I got it working by adding the "gcm_sender_id": in the manifest.webmanifest file (or manifest.json I also used firebase generated public and private keys.
your gcm_sender_id is your project id in google cloud or firebase sender id
Same situation and almost lost my sanity. I tried inserting gcm_sender_id with a Firebase senderId and worked finally. I didn't have a Firebase account, but I was able to create a project in seconds and my senderId was ready to be used in the messaging settings.
But a caveat: After my modification in the manifest.json (in my case) in the root's folder, it was needed to uninstall the current service worker and restart my React project. Then I followed again all steps back by asking permissions and subscribe the user and finally trigger a push notification.
During my heat researches for a solution, I found that gcm_sender_id is also used to send and validate push messages from other browsers. According to Google Web Updates:
For Chrome prior to version 52, Opera Android and the Samsung Browser,
you're also still required to include a 'gcm_sender_id' in your web
app's manifest.json. The API key and sender ID are used to check
whether the server making the requests is actually allowed to send
messages to the receiving user.

Keep track of installed pwa instances

We want to keep track of each pwa installation for a user. So we could track notifications, like did every instance of the app user installed (pc or phone, or ff, or chrome) have received the update. Can we know the pwa instance was uninstalled? Can we know web push was delivered to every instance?
In your service worker, fire a http post to your server in the "install" event. You'll need to get your userID from indexdb or similar. Use "fetch" not xmlhttp the service worker.
self.addEventListener('install', function(e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function(cache) {
console.log('[ServiceWorker] Caching app shell');
var rc = cache.addAll(filesToCache);
postServerStatus( "installcomplete" );
return rc;
})
);
});
function postServerStatus( strStatus ) {
var strUserID = "getfromindexdb";
fetch('./datasvc.aspx', {
method: 'post',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify({
service: strStatus,
userid: strUserID
}),
});
}