Caching the results of long browser-based operations in Local Storage

Datetime:2016-08-23 03:01:15          Topic:          Share

In the IoT-related (and Forge Viewer-based) prototype I’m spending most of my time working on, we have a long startup operation that instantiates a number of arrays of data with information derived from the BIM. This operation only really needs to be done once per model – every user will get exactly the same information from the model that’s loaded in their own browser instance – but we were calculating it on every load of the model in the Forge Viewer.

The question I’d like to look at in this post is the appropriate method for memoization of this function call.

I’vementioned in the past that we can now offload this kind of operation to the server – perhaps when the model is uploaded and translated, for instance – using the Model Derivative API . That would make a lot of sense – and is the preferred longer-term solution – but it also requires a bit more infrastructure work to make happen (we need server-side processing, storage and an API to access it). Another quick and not-particularly-dirty approach is to cache the results for each model on the local client machine and load them (if they exist) from there.

Which means the operation goes from being run on every load of the model to being run only the first time the model gets loaded in a particular browser on a particular system. Every user will still have to go through one (relatively) slow load of the model, but things will be much quicker for subsequent loads.

The best news is that it’s *really* easy to store information in a browser’s Local Storage . And the results – in our case, at least – were pretty remarkable.

Here are the TypeScript functions I wrote to save to and read from Local Storage:

public storeObject(key: string , value: any ): void {

localStorage.setItem(

this ._buildingMetadata.urn + key, JSON.stringify(value)

);

}

public getObject(key: string ): any {

var value = localStorage.getItem( this ._buildingMetadata.urn + key);

return value && JSON.parse(value);

}

The _buildingMetadata member contains information about the BIM, including the URN we load it from. This is a handy prefix for making sure we keep the information unique to a single model.

On load we have a “restoreFromStorage” function which tries to get the various objects from Local Storage: if it’s unsuccessful at any point we go ahead and process the metadata to create our objects. Which we then save to Local Storage for the next time we load.

If you open up the browser – in my case Chrome – you can check (and edit) the contents of Local Storage via More Tools –> Developer Tools –> Application –> Local Storage (and then select your domain). You’ll even see some Forge Viewer items in there:

I haven’t specifically benchmarked the performance of this – it depends on the model and on the system crunching the numbers – but for our models the load time for the second and subsequent loads reduces to a fraction of what it was for the first. Which proves the value of doing this centrally via the Model Derivative API, also.