W3C home > Mailing lists > Public > public-html@w3.org > June 2008

RE: DOM Storage feedback

From: Ian Hickson <ian@hixie.ch>
Date: Fri, 20 Jun 2008 22:15:56 +0000 (UTC)
To: Zhenbin Xu <Zhenbin.Xu@microsoft.com>
Cc: Ian Hickson <IMCEAMAILTO-ian+40hixie+2Ech@windows.microsoft.com>, "public-html-comments@w3.org" <public-html-comments@w3.org>, "public-html@w3.org" <public-html@w3.org>, Sunava Dutta <sunavad@windows.microsoft.com>, IE8 Core AJAX SWAT Team <ieajax@microsoft.com>
Message-ID: <Pine.LNX.4.62.0806202207130.13974@hixie.dreamhostps.com>

On Fri, 20 Jun 2008, Zhenbin Xu wrote:
> 
> More explicit would be nice - especially the synchronous API but 
> asynchronous storage part.

Ok, I'll make a note to update this.


> > But the problem is that the above would fail if the component from 
> > developer 2 uses .begin() or .commit(),
> 
> This issue is commonly solved by strict coding guideline.

An API that _requires_ strict coding guidelines to be usefully used is not 
a well designed API, and it is _esepcially_ not a good API for the Web.


> > Right now you can avoid all these problems by just doing:
> >
> >    var success = false;
> >    try {
> >      var id = localStorage['last-id'] + 1;
> >      localStorage['last-id'] = id;
> >      localStorage['email-ready-' + id] = "0"; // "begin"
> >
> >      localStorage['email-subject-' + id] = getSubject();
> >      localStorage['email-from-' + id] = resolveEmailAlias(from);
> >      localStorage['email-to-' + id] = resolveEmailAlias(to);
> >      localStorage['email-body-' + id] = getBody();
> >
> >      success = true;
> >    } catch (e) {
> >      // report or resolve e if necessary
> 
> Not easy for script recover from exception. Either some garbage are left 
> in localStorage, or a more complex scheme is needed.

Not at all, my examples all had recovery that removed the bogus content:

> >    }
> >    if (success) {
> >      localStorage['email-ready-' + id] = "1"; // "commit"
> >    } else {
> >      localStorage.removeItem('email-subject-' + id);
> >      localStorage.removeItem('email-from-' + id);
> >      localStorage.removeItem('email-to-' + id);
> >      localStorage.removeItem('email-body-' + id);
> >      localStorage.removeItem('email-ready-' + id); // "cancel"
> >    }
> >
> > This can easily be wrapped into a utility method that takes a single
> > method as its only argument:
> >
> >    function transactionAdd(body) {
> >      var success = false;
> >      var keys = [];
> >      try {
> >        var id = localStorage['last-id'] + 1;
> 
> If the id is persisting on disk and ever increasing, there is a danger 
> of overflow. So a more elaborated scheme may be needed here.

You'd have to be increasing the ID one hundred times per second for over 
two million years to overflow the integer range of the JS Number type. I 
don't think that's a problem.


> >        localStorage['last-id'] = id;
> >        localStorage['block-' + id] = "0"; // "begin"
> >
> >        body(function (name, value) {
> >          localStorage['block-' + id + '-' + name] = value;
> >          keys.push(name);
> >        });
> >
> >        success = true;
> >      } catch (e) {
> >        // report or resolve e if necessary
> 
> It is difficult to do any meaningful error handling inside an utility 
> function since it lacks context. Better leave it to the callers who have 
> more information about the situation.

The utility function could be adjusted as needed. For the example I gave, 
the function handled the errors fine, I don't really see a problem.


> >      }
> >      if (success) {
> >        localStorage['block-' + id] = "1"; // "commit"
> >      } else {
> >        for (var i in keys)
> >          localStorage.removeItem('block-' + id + '-' + keys[i]);
> >        localStorage.removeItem('block-' + id); // "cancel"
> >      }
> >      return success;
> >    }
> >
> > You would use this like this:
> >
> >    transactionAdd(function(add) {
> >      add('subject', getSubject());
> >      add('from', resolveEmailAlias(from));
> >      add('to', resolveEmailAlias(to));
> >      add('body', getBody());
> >    });
> >
> 
> How would application retrieve particular item later given that it has 
> no knowledge of what block id is?

Oops, the end of the utility function should be:

   if (success)
     return id;
   return 0;

...and the caller should store transactionAdd()'s return value.


> If a wrapper function is needed all the time, why not make it as part of 
> the platform?

Because it's not needed. When a transaction API is actually needed, the 
Database API is the one that should be used (and it has support for 
transactions built-in as a first-class object). The DOM Storage API isn't 
supposed to be used for structured data, it's just a name/value pair API. 
I'm just showing that it _can_ support transactions if someone really 
wants to do it.


Again, please, if you could commit to either removing or renaming (with an 
"ms" prefix) the non-standard event and methods that you implemented in 
IE8 to indicate that they are proprietary extensions, we would really 
appreciate it. We don't want to confuse authors on the platform who might 
test in one browser and find things don't work in another browser. 
Thanks!

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
Received on Friday, 20 June 2008 22:16:32 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Wednesday, 9 May 2012 00:16:18 GMT