Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding examples for “versionchange” and “blocked”. #133

Merged
merged 4 commits into from
Jan 9, 2017
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
89 changes: 88 additions & 1 deletion index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ db.close();

In the future, the database may have grown to contain other object
stores and indexes. The following example shows one way to handle
opening an older version of the database.
migrating from an older version of the database.

<pre class=lang-javascript>
var request = indexedDB.open("library", 3); // Request version 3.
Expand Down Expand Up @@ -277,7 +277,94 @@ request.onsuccess = function() {
db = request.result; // db.version will be 3.
};
</pre>
</aside>

<aside class=example id=handling-versionchange>
A single database can be used by multiple clients (pages and workers)
simultaneously - transactions ensure they don't clash while reading and writing.
However, if a new client wants to upgrade the database (via the "upgradeneeded"
event), it cannot do so until all other clients close their connection to the
current version of the database.

To avoid blocking a new client from upgrading, clients should listen for the
"versionchange" event. This fires when another client is wanting to upgrade the
database. To allow this to continue, react to the "versionchange" event by doing
something that ultimately closes this client's connection to the database.

One way of doing this is to reload the page:

<pre class=lang-javascript>
db.onversionchange = function() {
// First, save any unsaved data:
saveUnsavedData().then(function() {
// If the document isn't being actively used, it may be appropriate to reload
// the page without the user's interaction.
if (!document.hasFocus()) {
location.reload();
// Reloading will close the database, and also reload with the new JavaScript
// and database definitions.
} else {
// If the document has focus, it may be too disruptive to reload the page.
// Maybe ask the user to do it manually:
displayMessage("Please reload this page for the latest version.");
}
});
};

function saveUnsavedData() {
// How you do this depends on your app.
}

function displayMessage() {
// Show a non-modal message to the user.
}
</pre>

Another way is to call the database's close method. Other code on your page
should react to the database's "close" event, so it knows the database is no
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The close event only fires when the connection closes abnormally, e.g. when the user deletes browsing data or there is corruption or an I/O error. If close() is called explicitly the event does not fire.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And therefore it might be worth adding a note to the onclose definition that it's only fired in abnormal close scenarios. Look for the forced close flag.

longer accessible.

<pre class=lang-javascript>
db.onversionchange = function() {
saveUnsavedData().then(function() {
db.close();
});
};

db.addEventListener('close', function() {
// Put the app into a state where it no longer uses the database.
});
</pre>

The new client (the one attempting the upgrade) can use the "blocked" event to
detect if other clients are preventing the upgrade from happening. The "blocked"
event fires if other clients still hold a connection to the database after their
"versionchange" events have fired.

<pre class=lang-javascript>
var request = indexedDB.open("library", 4); // Request version 4.
var blockedTimeout;

request.onblocked = function() {
// Give the other clients time to save data asynchronously.
blockedTimeout = setTimeout(function() {
displayMessage("Upgrade blocked - Please close other tabs displaying this site.");
}, 1000);
};

request.onupgradeneeded = function(event) {
clearTimeout(blockedTimeout);
hideMessage();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably have // ... here indicating proceeding with the usual open steps

// ...
};

function hideMessage() {
// Hide a previously displayed message.
}
</pre>

The user will only see the above message if another client fails to disconnect
from the database. Ideally the user will never see this.
</aside>

<!-- ============================================================ -->
Expand Down