I am creating a offline first blogging platform which utilises IndexedDB and service workers. The idea here is if the user is offline and trying to send a post - send it in the background. This project is for my dissertation, I have only been looking at promises for a week or so - apologies if it is a simple error!
From my action in react/redux, i'm sending the sync event through successfully.
Below is the code for my sync event handler
self.addEventListener('sync', function(event) {
if (event.tag == 'send_post') {
//const URL
console.log('sync from SW - send post');
//this should try again if promise is rejected
event.waitUntil(
openDatabase('Outbox').then( (db) => {
return databaseGet('posts',db).then( (posts) => {
return sendAllFromOutbox(posts)
} )
} )
);
}
});
Below is openDatabase - (IndexedDB)
function openDatabase(name) {
return new Promise(function(resolve, reject) {
var version = 10;
var request = indexedDB.open(name, version);
var db;
request.onupgradeneeded = function(e) {
db = e.target.result;
e.target.transaction.onerror = reject;
};
request.onsuccess = function(e) {
db = e.target.result;
console.log('OPENED DATABASE');
resolve(db);
};
request.onerror = reject;
});
}
Below is databaseGet
function databaseGet(type,db) {
return new Promise(function(resolve, reject) {
var transaction = db.transaction([type], 'readonly');
var store = transaction.objectStore(type);
var request = store.getAll();
request.onsuccess = function(e) {
var result = e.target.result;
resolve(result);
};
request.onerror = reject;
});
}
And finally, below is sendAllFromOutbox
function sendAllFromOutbox(posts) {
return fetch('https://stirapi.herokuapp.com/sendPost', {
headers: {'Content-Type': 'application/json'},
method: "POST",
body: JSON.stringify(posts)
})
.then( (response) => {
console.log('response from SW sendAllFromOutbox', response);
} )
.catch( (err) => {
console.log('error from SW sendAllFromOutbox',err);
} )
}
From my understanding, if sendAllFromOutbox fails/rejects - it should get called again. But it doesn't seem to be getting called - and therefore is not being sent in the background.
If you would like to check out my repo - it's here https://github.com/georgecook92/Stir.
Thank you!
George
It's down to the browser to decide when the failed sync event should be retried. Also, it won't retry infinitely, but you know it's the last attempt via syncEvent.lastChance
(spec).
Looking at your code above, databaseGet
expects (type,db)
, but you call it databaseGet('posts')
, so that'll throw an error when you try and access properties of db
, which is undefined. Chrome's devtools should show this, especially with "break on caught errors".
The idea here is if the user is offline and trying to send a post - send it in the background
It's best to use background sync regardless of the user's current state. Sure, navigator.onLine
will tell you if the user is definitely offline, but if onLine
is true the user still may not have a reliable connection.