localstorageshim
localstorageshim copied to clipboard
Minimize race conditions
UserData isn't synchronous and this hindrance is further exaggerated by the fact that we're loading things in an iframe. For example, it's pretty hit or miss if the following works:
<script src="localstorageshim.js" type="text/javascript"></script>
<script type="text/javascript">
document.write(typeof(localStorage));//undefined or object
</script>
Do things to fix/minimize this!
How do you suppose we fix this?
By calling some type of ready method on the iframe onload and then doing localStorage access only inside that ready method?
Yeah, that's definitely one option (and probably the easiest). However, I'm a little hesitant to go that route because I'd really like to keep this as close to the real localStorage API as possible. And, I still think there's some exploration to do trying to find a way to get that iframe to essentially 'block' until UserData is ready. For example, there's an ActiveX control to embed a whole html document inside of the currently running script instead of appending it to the dom... Another option would be to make the localStorage object always available, but, data from UserData would propagate over whenever it's ready... not sure what would happen if there were conflicts, though :/
Either case, I'll try to block off some time this weekend to try to come up w/ some solutions, but, let me know if you have any other ideas :)
What about returning promises? Something like:
localStorage.getItem('test').then(function(data){
// do something
});
FYI, you can make the userData element available synchronously by forcibly closing the document that is still open in the iframe's content window and then manually injecting the required DOM structure into the iframe. That way you don't have to wait for the load event on the iframe.
E.g.
function createUserDataStore( frame, storeId ) {
var doc, html, body, frame, store, insert;
doc = frame.contentWindow.document;
doc.close();
if ( !doc.documentElement ) {
html = doc.createElement( "html" );
body = doc.createElement( "body" );
html.appendChild( body );
doc.appendChild( html );
}
if ( !doc.body ) {
body = doc.createElement( "body" );
( html || doc.documentElement ).appendChild( body );
}
// Create an element carrying the userData storage behavior.
store = doc.createElement( "ie:userdata" );
store.id = storeId;
store.addBehavior( "#default#userData" );
( body || doc.body ).appendChild( store );
return store;
}
Note however that when I discovered this I was using 0 byte HTML file, first loaded synchronously through a <script>
tag. Not sure if it will also work with the mhtml trick; YMMV.