{"action":"created","issue":{"url":"https://api.github.com/repos/slightlyoff/BackgroundSync/issues/72","labels_url":"https://api.github.com/repos/slightlyoff/BackgroundSync/issues/72/labels{/name}","comments_url":"https://api.github.com/repos/slightlyoff/BackgroundSync/issues/72/comments","events_url":"https://api.github.com/repos/slightlyoff/BackgroundSync/issues/72/events","html_url":"https://github.com/slightlyoff/BackgroundSync/issues/72","id":65660243,"number":72,"title":"Guarding data posts against closing the tab","user":{"login":"jakearchibald","id":93594,"avatar_url":"https://avatars.githubusercontent.com/u/93594?v=3","gravatar_id":"","url":"https://api.github.com/users/jakearchibald","html_url":"https://github.com/jakearchibald","followers_url":"https://api.github.com/users/jakearchibald/followers","following_url":"https://api.github.com/users/jakearchibald/following{/other_user}","gists_url":"https://api.github.com/users/jakearchibald/gists{/gist_id}","starred_url":"https://api.github.com/users/jakearchibald/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jakearchibald/subscriptions","organizations_url":"https://api.github.com/users/jakearchibald/orgs","repos_url":"https://api.github.com/users/jakearchibald/repos","events_url":"https://api.github.com/users/jakearchibald/events{/privacy}","received_events_url":"https://api.github.com/users/jakearchibald/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":14,"created_at":"2015-04-01T11:04:31Z","updated_at":"2015-06-12T17:20:06Z","closed_at":null,"body":"Consider this:\r\n\r\n```js\r\naddToOutbox(importantEmail);\r\n\r\nfetch(url, {\r\n  method: 'POST',\r\n  body: importantEmail\r\n}).then(response => {\r\n  if (!response.ok) throw Error(response.statusText);\r\n  removeFromOutbox(importantEmail);\r\n  showSuccessUI();\r\n}).catch(function() {\r\n  return navigator.serviceWorker.ready.then(reg => {\r\n    return reg.sync.register({tag: 'outbox'});\r\n  });\r\n});\r\n```\r\n\r\nIf sending an email fails, we request a sync and handle it later. However, if the tab/browser closes before the request completes, or the page navigates away, the request fails but we never get the chance to send that request.\r\n\r\nData isn't lost, but we can't send that email in the background. It becomes more attractive to do this:\r\n\r\n```js\r\naddToOutbox(importantEmail);\r\n\r\nnavigator.serviceWorker.ready.then(reg => {\r\n  return reg.sync.register({tag: 'outbox'})\r\n});\r\n\r\nfetch(url, {\r\n  method: 'POST',\r\n  body: importantEmail\r\n}).then(response => {\r\n  if (!response.ok) throw Error(response.statusText);\r\n  removeFromOutbox(importantEmail);\r\n  showSuccessUI();\r\n\r\n  if (outboxEmpty) {\r\n    navigator.serviceWorker.ready.then(reg => {\r\n      return reg.sync.getRegistration('outbox');\r\n    }).then(syncReg => syncReg.unregister());\r\n  }\r\n});\r\n```\r\n\r\nAs in, we schedule a sync with every important `POST`, and unregister it if it succeeds. I'm worried there may be a race here where the sync event fires file the fetch is still being attempted, resulting in a double fetch.\r\n\r\nI could schedule a sync event and do all of my outbox emptying there (not from the page at all), but I have no guarantee that it'll happen immediately, and communicating success/failure back to the page is a bit of a `postMessage` mess.\r\n\r\nIs there anything we can do to improve this? Should we?\r\n\r\nCouple of half-baked ideas:\r\n\r\n```js\r\nreg.sync.register({\r\n  tag: 'outbox',\r\n  onlySyncIfThisPromiseFailsToFulfill: fetch(url, {\r\n    method: 'POST',\r\n    body: importantEmail\r\n  }).then(response => {\r\n    if (!response.ok) throw Error(response.statusText);\r\n  })\r\n});\r\n```\r\n\r\nOr:\r\n\r\n```js\r\nreg.sync.register({\r\n  tag: 'outbox',\r\n  onlySyncIfNoPagesAreOpen: true\r\n});\r\n```\r\n\r\n…which would prevent race conditions with the page."},"comment":{"url":"https://api.github.com/repos/slightlyoff/BackgroundSync/issues/comments/111564019","html_url":"https://github.com/slightlyoff/BackgroundSync/issues/72#issuecomment-111564019","issue_url":"https://api.github.com/repos/slightlyoff/BackgroundSync/issues/72","id":111564019,"user":{"login":"jkarlin","id":6920902,"avatar_url":"https://avatars.githubusercontent.com/u/6920902?v=3","gravatar_id":"","url":"https://api.github.com/users/jkarlin","html_url":"https://github.com/jkarlin","followers_url":"https://api.github.com/users/jkarlin/followers","following_url":"https://api.github.com/users/jkarlin/following{/other_user}","gists_url":"https://api.github.com/users/jkarlin/gists{/gist_id}","starred_url":"https://api.github.com/users/jkarlin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jkarlin/subscriptions","organizations_url":"https://api.github.com/users/jkarlin/orgs","repos_url":"https://api.github.com/users/jkarlin/repos","events_url":"https://api.github.com/users/jkarlin/events{/privacy}","received_events_url":"https://api.github.com/users/jkarlin/received_events","type":"User","site_admin":false},"created_at":"2015-06-12T17:20:06Z","updated_at":"2015-06-12T17:20:06Z","body":"+1, syncReg.done seems useful"}}