Using HTML5/Javascript in Windows Store apps: Data access and storage mechanism (III)

Introduction

Windows Store app offers lots of methods for data access and storage. And this article will only focus on HTML5/JavaScript programming.

In this tutorial, we’ll go over Application Data, File API , HTML5 Web Storage, Indexed Database API and remote data access. With these you can store more data – and store it more efficiently.

Handle Large Data

Generally, we can store data with IndexedDB in Windows Store app (Html5/JavaScript). Indexed Database, each app has a quota of 250MB. Among all apps on the device, the limit is 4% of the disk size or 20GB, whichever is smaller. For hard drives that are less than 30GB, the limit among all apps on the device is 375MB. Because of the overall quota among all apps, test your app to ensure its functions properly when it can store very little or even no data because other apps consume the overall quota.

And if you want to upload or download large resources, we recommend Background Transfer. Background Transfer is primarily designed for long-term transfer operations for resources like video, music and large images. For short-term operations involving transfers of smaller resources (i.e. a couple KB), the use of provided HTTP APIs (XHR in JavaScript) is recommended.

Indexed Database

To demonstrate how to use IndexedDB in a real project, I make a simple application “Creating a List with ListView and IndexedDB”.

This application stores all of its data in an IndexedDB database named ListDB. This database is opened/created with the following code:

        var db;

        var req = window.msIndexedDB.open("ListDB", 1);

        req.onerror = function () {

            console.log("Could not open database");

        };

        req.onupgradeneeded = function (event) {

            var newDB = event.target.result;

            newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement: true });

        };

The msIndexedDB.open() method accepts two parameters: the name of the database to open and the version of the database to open. If a database with a matching version already exists, then calling the msIndexedDB.open() method opens a connection to the existing database. If the database does not exist then the upgradeneeded event is raised. You handle the upgradeneeded event to create a new database. In the code above, the upgradeneeded event handler creates an object store named “tasks” (An object store roughly corresponds to a database table). When you add items to the tasks object store then each item gets an id property with an auto-incremented value automatically. The code above also includes an error event handler. If the IndexedDB database cannot be opened or created, for whatever reason, an error message is written to the Visual Studio 2012 JavaScript Console window.

You can bind the datasource and edit the listview as follow:

    // Create the data source

    var tasks = new WinJS.Binding.List();

 

    // Open the database

    var db;

    var req = window.msIndexedDB.open("ListDB", 1);

    req.onerror = function () {

        console.log("Could not open database");

    };

    req.onupgradeneeded = function (event) {

        var newDB = event.target.result;

        newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement: true });

    };

 

    // Load the data source with data from the database

    req.onsuccess = function () {

        db = req.result;

        var tran = db.transaction("tasks");

        tran.objectStore("tasks").openCursor().onsuccess = function (event) {

            var cursor = event.target.result;

            if (cursor) {

                tasks.dataSource.insertAtEnd(null, cursor.value);

                cursor.continue();

            };

        };

 

    };

 

    // Add a new task

    function addTask(taskToAdd) {

        var transaction = db.transaction("tasks", "readwrite");

        var addRequest = transaction.objectStore("tasks").add(taskToAdd);

        addRequest.onsuccess = function (evt) {

            taskToAdd.id = evt.target.result;

            tasks.dataSource.insertAtEnd(null, taskToAdd);

        }

    }

 

    // Delete an existing task

    function deleteTask(listViewItem) {

        // Database key != ListView key

        var dbKey = listViewItem.data.id;

        var listViewKey = listViewItem.key;

 

        // Remove item from db and, if success, remove item from ListView

        var transaction = db.transaction("tasks", "readwrite");

        var deleteRequest = transaction.objectStore("tasks").delete(dbKey);

        deleteRequest.onsuccess = function () {

            tasks.dataSource.remove(listViewKey);

        }

    }

 

    // Expose the data source and functions

    WinJS.Namespace.define("TaskList", {

        tasks: tasks,

        addTask: addTask,

        deleteTask: deleteTask

    });

And you can download the complete code in attachment.

Background Transfer

There are two main classes, BackgroundDownloader and BackgroundUploader. BackgroundDownloader is used to configure downloads prior to the actual creation of the download operation using CreateDownload. BackgroundUploader is used to configure upload prior to the actual creation of the upload operation using CreateUpload.

For example, you can configure and begin a basic download operation as follow:

        var download = null;

        var promise = null;

 

        function DownloadFile(uriString, fileName) {

            try {

                // Asynchronously create the file in the pictures folder.

                Windows.Storage.KnownFolders.picturesLibrary.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.generateUniqueName).done(function (newFile) {

                    var uri = Windows.Foundation.Uri(uriString);

                    var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();

 

                    // Create a new download operation.

                    download = downloader.createDownload(uri, newFile);

 

                    // Start the download and persist the promise to be able to cancel the download.

                    promise = download.startAsync().then(complete, error, progress);

                }, error);

            } catch (err) {

                displayException(err);

            }

        };

You can configure and begin a basic upload operation as follow:

        var upload = null;

        var promise = null;

 

        function UploadFile(uriString, file) {

            try {

 

                var uri = Windows.Foundation.Uri(uriString);

                var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();

 

                // Set a header, so the server can save the file (this is specific to the sample server).

                uploader.setRequestHeader("Filename", file.name);

 

                // Create a new upload operation.

                upload = uploader.createUpload(uri, file);

 

                // Start the upload and persist the promise to be able to cancel the upload.

                promise = upload.startAsync().then(complete, error, progress);

            } catch (err) {

                displayError(err);

            }

        };

And there has an example demonstrating how to use Background Transfer.

 

 

List.zip