Re: [IndexedDB] Events and requests

2011-01-11 Thread Keean Schupke
Comments inline:

On 11 January 2011 07:11, Axel Rauschmayer a...@rauschma.de wrote:

 Coming back to the initial message in this thread (at the very bottom):
 = General rule of thumb: clearly separate input data and output data.

 Using JavaScript dynamic nature, things could look as follows:

 indexedDB.open('AddressBook', 'Address Book', {
 success: function(evt) {
 },
 error: function(evt) {
 }
 });


Personally I prefer a single callback passed an object.

indexedDB.open('AddressBook', 'Address Book', function(event) {
switch(event.status) {
case EVENT_SUCCESS: 
break;
case EVENT_ERROR: 
break;
}
});

As it allows callbacks to be composed more easily.

- The last argument is thus the request and clearly input.

 - If multiple success handlers are needed, success could be an array of
 functions (same for error handlers).


multiple handlers can be passes using a composition function:

// can be defined in the library
var all = function(flist) {
   return function(event) {
   for (int i = 0; i  flist.length; i++) {
   flist[i](event);
   }
};
};

indexedDB.open('AddressBook', 'Address Book', all([fn1, fn2, fn3]));


Cheers,
Keean.



 - I would eliminiate readyState and move abort() to IDBEvent (=output and
 an interface to the DB client).

 - With subclasses of IDBEvent one has the choice of eliminating them by
 making their fields additional parameters of success() and error().
 event.result is a prime candidate for this!

 - This above way eliminates the need of manipulating the request *after* (a
 reference to) it has been placed in the event queue.

 Questions:

 - Is it really necessary to make IDBEvent a subclass of Event and thus drag
 the DOM (which seems to be universally hated) into IndexedDB?

 - Are there any other asynchronous DB APIs for dynamic languages that one
 could learn from (especially from mistakes that they have made)? They must
 have design principles and rationales one might be able to use. WebDatabase
 (minus schema plus cursor) looks nice.

 On Jan 10, 2011, at 23:40 , Keean Schupke wrote:

 Hi,

 I did say it was for fun!  If you think it should be suggested somewhere I
 am happy to do so. Note that  I renamed 'onsuccess' to 'bind' to show how it
 works as a monad, there is no need to do this (although I prefer to it to
 explicitly show it is a Monad).

 The definition of unit is simply:

 var unit = function(v) {
 return {
 onsuccess: function(f) {f(v);}
 };
 };

 And then you can compose callbacks using 'onsuccess'...

 you might like to keep onsuccess, and use result instead of unit... So
 simply using the above definition you can compose callbacks:

 var y =
 db.transaction([foo]).objectStore(foo).getM(mykey1).onsuccess(function(result1)
 {

  
 db.transaction([foo]).objectStore(foo).getM(mykey2).onsuccess(function(result2)
 {
 result(result1 + result2);
 });
 });


 Cheers,
 Keean.


 On 10 January 2011 22:31, Jonas Sicking jo...@sicking.cc wrote:

 This seems like something better suggeseted to the lists at ECMA where
 javascript (or rather ECMAScript) is being standardized. I hardly
 think that a database API like indexedDB is the place to redefine how
 javascript should handle asynchronous programming.

 / Jonas

 On Mon, Jan 10, 2011 at 2:26 PM, Keean Schupke ke...@fry-it.com wrote:
  Just to correct my cut and paste error, that was of course supposed to
 be:
  var y = do {
  result1 - db.transaction([foo]).objectStore(foo).getM(mykey1);
  result2 - db.transaction([foo]).objectStore(foo).getM(mykey2);
  unit(result1 + result2);
  }
 
  Cheers,
  Keean.
  On 10 January 2011 22:24, Keean Schupke ke...@fry-it.com wrote:
 
  Okay, sorry, the original change seemed sensible, I guess I didn't see
 how
  you got from there to promises.
 
  Here's some fun to think about as an alternative though:
 
  Interestingly the pattern of multiple callbacks, providing each
 callback
  is passed zero or one parameter forms a Monad.
  So for example if 'unit' is the constructor for the object returned
 from
  get then onsuccess it 'bind' and I can show that these obey the 3
 monad
  laws. Allowing composability of callbacks. So you effectively have:
  var x = db.transaction([foo]).objectStore(foo).getM(mykey);
  var y =
 
 db.transaction([foo]).objectStore(foo).getM(mykey1).bind(function(result1)
  {
 
 
  
 db.transaction([foo]).objectStore(foo).getM(mykey2).bind(function(result2)
  {
  unit(result1 + result2);
  });
  });
  The two objects returned x and y are both the same kind of object.
 y
  represents the sum or concatination of the results of the lookups
 mykey1
  and mykey2. You would use it identically to using the result of a
 single
  lookup:
  x.bind(function(result) {... display the result of a single lookup
 ...});
  y.bind(function(result) {... display the result of both lookups ...});
 
  If we could then have some syntactic 

Re: [IndexedDB] Events and requests

2011-01-11 Thread Axel Rauschmayer
Looks great, I just tried to stay as close to the current API as possible.

A single handler should definitely be enough. Can, say, a cursor be read 
multiple times (if there are several success handlers)? Doesn’t that make 
things more complicated?

On Jan 11, 2011, at 10:22 , Keean Schupke wrote:

 Comments inline:
 
 On 11 January 2011 07:11, Axel Rauschmayer a...@rauschma.de wrote:
 Coming back to the initial message in this thread (at the very bottom):
 = General rule of thumb: clearly separate input data and output data.
 
 Using JavaScript dynamic nature, things could look as follows:
 
 indexedDB.open('AddressBook', 'Address Book', {
 success: function(evt) {
 },
 error: function(evt) {
 }
 });
 
 Personally I prefer a single callback passed an object.
 
 indexedDB.open('AddressBook', 'Address Book', function(event) {
 switch(event.status) {
 case EVENT_SUCCESS: 
 break;
 case EVENT_ERROR: 
 break;
 }
 }); 
  
 As it allows callbacks to be composed more easily.
 
 - The last argument is thus the request and clearly input.
 
 - If multiple success handlers are needed, success could be an array of 
 functions (same for error handlers).
 
 multiple handlers can be passes using a composition function:
 
 // can be defined in the library
 var all = function(flist) {
return function(event) {
for (int i = 0; i  flist.length; i++) {
flist[i](event);
}
 };
 };
 
 indexedDB.open('AddressBook', 'Address Book', all([fn1, fn2, fn3]));
 
 
 Cheers,
 Keean.
 
 
 
 - I would eliminiate readyState and move abort() to IDBEvent (=output and an 
 interface to the DB client).
 
 - With subclasses of IDBEvent one has the choice of eliminating them by 
 making their fields additional parameters of success() and error(). 
 event.result is a prime candidate for this!
 
 - This above way eliminates the need of manipulating the request *after* (a 
 reference to) it has been placed in the event queue.
 
 Questions:
 
 - Is it really necessary to make IDBEvent a subclass of Event and thus drag 
 the DOM (which seems to be universally hated) into IndexedDB?
 
 - Are there any other asynchronous DB APIs for dynamic languages that one 
 could learn from (especially from mistakes that they have made)? They must 
 have design principles and rationales one might be able to use. WebDatabase 
 (minus schema plus cursor) looks nice.
 
 On Jan 10, 2011, at 23:40 , Keean Schupke wrote:
 
 Hi, 
 
 I did say it was for fun!  If you think it should be suggested somewhere I 
 am happy to do so. Note that  I renamed 'onsuccess' to 'bind' to show how it 
 works as a monad, there is no need to do this (although I prefer to it to 
 explicitly show it is a Monad).
 
 The definition of unit is simply:
 
 var unit = function(v) {
 return {
 onsuccess: function(f) {f(v);}
 };
 };
 
 And then you can compose callbacks using 'onsuccess'...
 
 you might like to keep onsuccess, and use result instead of unit... So 
 simply using the above definition you can compose callbacks:
 
 var y = 
 db.transaction([foo]).objectStore(foo).getM(mykey1).onsuccess(function(result1)
  {
 
 db.transaction([foo]).objectStore(foo).getM(mykey2).onsuccess(function(result2)
  {
 result(result1 + result2);
 });
 }); 
 
 
 Cheers,
 Keean.
 
 
 On 10 January 2011 22:31, Jonas Sicking jo...@sicking.cc wrote:
 This seems like something better suggeseted to the lists at ECMA where
 javascript (or rather ECMAScript) is being standardized. I hardly
 think that a database API like indexedDB is the place to redefine how
 javascript should handle asynchronous programming.
 
 / Jonas
 
 On Mon, Jan 10, 2011 at 2:26 PM, Keean Schupke ke...@fry-it.com wrote:
  Just to correct my cut and paste error, that was of course supposed to be:
  var y = do {
  result1 - db.transaction([foo]).objectStore(foo).getM(mykey1);
  result2 - db.transaction([foo]).objectStore(foo).getM(mykey2);
  unit(result1 + result2);
  }
 
  Cheers,
  Keean.
  On 10 January 2011 22:24, Keean Schupke ke...@fry-it.com wrote:
 
  Okay, sorry, the original change seemed sensible, I guess I didn't see how
  you got from there to promises.
 
  Here's some fun to think about as an alternative though:
 
  Interestingly the pattern of multiple callbacks, providing each callback
  is passed zero or one parameter forms a Monad.
  So for example if 'unit' is the constructor for the object returned from
  get then onsuccess it 'bind' and I can show that these obey the 3 monad
  laws. Allowing composability of callbacks. So you effectively have:
  var x = db.transaction([foo]).objectStore(foo).getM(mykey);
  var y =
  db.transaction([foo]).objectStore(foo).getM(mykey1).bind(function(result1)
  {
 
   
  db.transaction([foo]).objectStore(foo).getM(mykey2).bind(function(result2)
  {
  unit(result1 + result2);
  });
  });
  The two objects returned x and y are both the same 

Re: [IndexedDB] Events and requests

2011-01-11 Thread Keean Schupke
If one handler changes the state who knows what will happen. I guess the
order in which handers are called is significant. That's one advantage to
using a function like all to compose callbacks - its very clear what order
they get called in. You could call it 'sequence' to make it even clearer
(that they are called one at a time left to right, not in parallel).

You could make the callback an optional parameter, and use it if supplied,
and return an object (for the existing API if none is supplied).


Cheers,
Keean.


On 11 January 2011 09:31, Axel Rauschmayer a...@rauschma.de wrote:

 Looks great, I just tried to stay as close to the current API as possible.

 A single handler should definitely be enough. Can, say, a cursor be read
 multiple times (if there are several success handlers)? Doesn’t that make
 things more complicated?

 On Jan 11, 2011, at 10:22 , Keean Schupke wrote:

 Comments inline:

 On 11 January 2011 07:11, Axel Rauschmayer a...@rauschma.de wrote:

 Coming back to the initial message in this thread (at the very bottom):
 = General rule of thumb: clearly separate input data and output data.

 Using JavaScript dynamic nature, things could look as follows:

 indexedDB.open('AddressBook', 'Address Book', {
 success: function(evt) {
 },
 error: function(evt) {
 }
 });


 Personally I prefer a single callback passed an object.

 indexedDB.open('AddressBook', 'Address Book', function(event) {
 switch(event.status) {
 case EVENT_SUCCESS: 
 break;
 case EVENT_ERROR: 
 break;
 }
 });

 As it allows callbacks to be composed more easily.

 - The last argument is thus the request and clearly input.

 - If multiple success handlers are needed, success could be an array of
 functions (same for error handlers).


 multiple handlers can be passes using a composition function:

 // can be defined in the library
 var all = function(flist) {
return function(event) {
for (int i = 0; i  flist.length; i++) {
flist[i](event);
}
 };
 };

 indexedDB.open('AddressBook', 'Address Book', all([fn1, fn2, fn3]));


 Cheers,
 Keean.



 - I would eliminiate readyState and move abort() to IDBEvent (=output and
 an interface to the DB client).

 - With subclasses of IDBEvent one has the choice of eliminating them by
 making their fields additional parameters of success() and error().
 event.result is a prime candidate for this!

 - This above way eliminates the need of manipulating the request *after*
 (a reference to) it has been placed in the event queue.

 Questions:

 - Is it really necessary to make IDBEvent a subclass of Event and thus
 drag the DOM (which seems to be universally hated) into IndexedDB?

 - Are there any other asynchronous DB APIs for dynamic languages that one
 could learn from (especially from mistakes that they have made)? They must
 have design principles and rationales one might be able to use. WebDatabase
 (minus schema plus cursor) looks nice.

 On Jan 10, 2011, at 23:40 , Keean Schupke wrote:

 Hi,

 I did say it was for fun!  If you think it should be suggested somewhere I
 am happy to do so. Note that  I renamed 'onsuccess' to 'bind' to show how it
 works as a monad, there is no need to do this (although I prefer to it to
 explicitly show it is a Monad).

 The definition of unit is simply:

 var unit = function(v) {
 return {
 onsuccess: function(f) {f(v);}
 };
 };

  And then you can compose callbacks using 'onsuccess'...

 you might like to keep onsuccess, and use result instead of unit... So
 simply using the above definition you can compose callbacks:

 var y =
 db.transaction([foo]).objectStore(foo).getM(mykey1).onsuccess(function(result1)
 {

  
 db.transaction([foo]).objectStore(foo).getM(mykey2).onsuccess(function(result2)
 {
 result(result1 + result2);
 });
 });


 Cheers,
 Keean.


 On 10 January 2011 22:31, Jonas Sicking jo...@sicking.cc wrote:

 This seems like something better suggeseted to the lists at ECMA where
 javascript (or rather ECMAScript) is being standardized. I hardly
 think that a database API like indexedDB is the place to redefine how
 javascript should handle asynchronous programming.

 / Jonas

 On Mon, Jan 10, 2011 at 2:26 PM, Keean Schupke ke...@fry-it.com wrote:
  Just to correct my cut and paste error, that was of course supposed to
 be:
  var y = do {
  result1 - db.transaction([foo]).objectStore(foo).getM(mykey1);
  result2 - db.transaction([foo]).objectStore(foo).getM(mykey2);
  unit(result1 + result2);
  }
 
  Cheers,
  Keean.
  On 10 January 2011 22:24, Keean Schupke ke...@fry-it.com wrote:
 
  Okay, sorry, the original change seemed sensible, I guess I didn't see
 how
  you got from there to promises.
 
  Here's some fun to think about as an alternative though:
 
  Interestingly the pattern of multiple callbacks, providing each
 callback
  is passed zero or one parameter forms a Monad.
  So for example 

Re: [IndexedDB] Events and requests

2011-01-10 Thread ben turner
FWIW Jonas' proposed changes have been implemented and will be
included in Firefox 4 Beta 9, due out in a few days.

-Ben

On Fri, Dec 10, 2010 at 12:47 PM, Jonas Sicking jo...@sicking.cc wrote:
 I've been reaching out to get feedback, but no success yet. Will re-poke.

 / Jonas

 On Fri, Dec 10, 2010 at 4:33 AM, Jeremy Orlow jor...@chromium.org wrote:
 Any additional thoughts on this?  If no one else cares, then we can go with
 Jonas' proposal (and we should file a bug).
 J

 On Thu, Nov 11, 2010 at 12:06 PM, Jeremy Orlow jor...@chromium.org wrote:

 On Tue, Nov 9, 2010 at 11:35 AM, Jonas Sicking jo...@sicking.cc wrote:

 Hi All,

 One of the things we briefly discussed at the summit was that we
 should make IDBErrorEvents have a .transaction. This since we are
 allowing you to place new requests from within error handlers, but we
 currently provide no way to get from an error handler to any useful
 objects. Instead developers will have to use closures to get to the
 transaction or other object stores.

 Another thing that is somewhat strange is that we only make the result
 available through the success event. There is no way after that to get
 it from the request. So instead we use special event interfaces with
 supply access to source, transaction and result.

 Compare this to how XMLHttpRequests work. Here the result and error
 code is available on the request object itself. The 'load' event,
 which is equivalent to our 'success' event didn't supply any
 information until we recently added progress event support. But still
 it only supplies information about the progress, not the actual value
 itself.

 One thing we could do is to move

 .source
 .transaction
 .result
 .error

 to IDBRequest. Then make success and error events be simple events
 which only implement the Event interface. I.e. we could get rid of the
 IDBEvent, IDBSuccessEvent, IDBTransactionEvent and IDBErrorEvent
 interfaces.

 We'd still have to keep IDBVersionChangeEvent, but it can inherit
 Event directly.

 The request created from IDBFactory.open would return a IDBRequest
 where .transaction and .source is null. We already fire a IDBEvent
 where .source is null (actually, the spec currently doesn't define
 what the source should be I see now).


 The only major downside with this setup that I can see is that the
 current syntax:

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.result);
 }

 would turn into the slightly more verbose

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.target.result);
 }

 (And note that with the error handling that we have discussed, the
 above code snippets are actually plausible (apart from the alert() of
 course)).

 The upside that I can see is that we behave more like XMLHttpRequest.
 It seems that people currently follow a coding pattern where they
 place a request and at some later point hand the request to another
 piece of code. At that point the code can either get the result from
 the .result property, or install a onload handler and wait for the
 result if it isn't yet available.

 However I only have anecdotal evidence that this is a common coding
 pattern, so not much to go on.

 Here's a counter proposal:  Let's add .transaction, .source, and .result
 to IDBEvent and just specify them to be null when there is no transaction,
 source, and/or result.  We then remove readyState from IDBResult as it
 serves no purpose.
 What I'm proposing would result in an API that's much more similar to what
 we have at the moment, but would be a bit different than XHR.  It is
 definitely good to have similar patterns for developers to follow, but I
 feel as thought the model of IndexedDB is already pretty different from XHR.
  For example, method calls are supplied parameters and return an IDBRequest
 object vs you using new to create the XHR object and then making method
 calls to set it up and then making a method call to start it.  In fact, if
 you think about it, there's really not that much XHR and IndexedDB have in
 common except that they use event handlers.
 As for your proposal, let me think about it for a bit and forward it on to
 some people I know who are playing with IndexedDB already.
 J






Re: [IndexedDB] Events and requests

2011-01-10 Thread Jonas Sicking
I did some outreach to developers and while I didn't get a lot of
feedback, what I got was positive to this change.

The basic use-case that was brought up was implementing a promises
which, as I understand it, works similar to the request model I'm
proposing. I.e. you build up these promise objects which represent a
result which may or may not have arrived yet. At some point you can
either read the value out, or if it hasn't arrived yet, register a
callback for when the value arrives.

It was pointed out that this is still possible with how the spec is
now, but it will probably result in that developers will come up with
conventions to set the result on the request themselves. This wouldn't
be terribly bad, but also seems nice if we can help them.

/ Jonas

On Mon, Jan 10, 2011 at 8:13 AM, ben turner bent.mozi...@gmail.com wrote:
 FWIW Jonas' proposed changes have been implemented and will be
 included in Firefox 4 Beta 9, due out in a few days.

 -Ben

 On Fri, Dec 10, 2010 at 12:47 PM, Jonas Sicking jo...@sicking.cc wrote:
 I've been reaching out to get feedback, but no success yet. Will re-poke.

 / Jonas

 On Fri, Dec 10, 2010 at 4:33 AM, Jeremy Orlow jor...@chromium.org wrote:
 Any additional thoughts on this?  If no one else cares, then we can go with
 Jonas' proposal (and we should file a bug).
 J

 On Thu, Nov 11, 2010 at 12:06 PM, Jeremy Orlow jor...@chromium.org wrote:

 On Tue, Nov 9, 2010 at 11:35 AM, Jonas Sicking jo...@sicking.cc wrote:

 Hi All,

 One of the things we briefly discussed at the summit was that we
 should make IDBErrorEvents have a .transaction. This since we are
 allowing you to place new requests from within error handlers, but we
 currently provide no way to get from an error handler to any useful
 objects. Instead developers will have to use closures to get to the
 transaction or other object stores.

 Another thing that is somewhat strange is that we only make the result
 available through the success event. There is no way after that to get
 it from the request. So instead we use special event interfaces with
 supply access to source, transaction and result.

 Compare this to how XMLHttpRequests work. Here the result and error
 code is available on the request object itself. The 'load' event,
 which is equivalent to our 'success' event didn't supply any
 information until we recently added progress event support. But still
 it only supplies information about the progress, not the actual value
 itself.

 One thing we could do is to move

 .source
 .transaction
 .result
 .error

 to IDBRequest. Then make success and error events be simple events
 which only implement the Event interface. I.e. we could get rid of the
 IDBEvent, IDBSuccessEvent, IDBTransactionEvent and IDBErrorEvent
 interfaces.

 We'd still have to keep IDBVersionChangeEvent, but it can inherit
 Event directly.

 The request created from IDBFactory.open would return a IDBRequest
 where .transaction and .source is null. We already fire a IDBEvent
 where .source is null (actually, the spec currently doesn't define
 what the source should be I see now).


 The only major downside with this setup that I can see is that the
 current syntax:

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.result);
 }

 would turn into the slightly more verbose

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.target.result);
 }

 (And note that with the error handling that we have discussed, the
 above code snippets are actually plausible (apart from the alert() of
 course)).

 The upside that I can see is that we behave more like XMLHttpRequest.
 It seems that people currently follow a coding pattern where they
 place a request and at some later point hand the request to another
 piece of code. At that point the code can either get the result from
 the .result property, or install a onload handler and wait for the
 result if it isn't yet available.

 However I only have anecdotal evidence that this is a common coding
 pattern, so not much to go on.

 Here's a counter proposal:  Let's add .transaction, .source, and .result
 to IDBEvent and just specify them to be null when there is no transaction,
 source, and/or result.  We then remove readyState from IDBResult as it
 serves no purpose.
 What I'm proposing would result in an API that's much more similar to what
 we have at the moment, but would be a bit different than XHR.  It is
 definitely good to have similar patterns for developers to follow, but I
 feel as thought the model of IndexedDB is already pretty different from 
 XHR.
  For example, method calls are supplied parameters and return an IDBRequest
 object vs you using new to create the XHR object and then making method
 calls to set it up and then making a method call to start it.  In fact, if
 you think about it, there's really not that much XHR and IndexedDB have in
 common except that they use event handlers.
 As for your proposal, let 

Re: [IndexedDB] Events and requests

2011-01-10 Thread Axel Rauschmayer
Promises/futures would be great, yes! Cleaner than the current solution. They 
are the right metaphor for this kind of thing.

http://en.wikipedia.org/wiki/Futures_and_promises

On Jan 10, 2011, at 22:31 , Jonas Sicking wrote:

 I did some outreach to developers and while I didn't get a lot of
 feedback, what I got was positive to this change.
 
 The basic use-case that was brought up was implementing a promises
 which, as I understand it, works similar to the request model I'm
 proposing. I.e. you build up these promise objects which represent a
 result which may or may not have arrived yet. At some point you can
 either read the value out, or if it hasn't arrived yet, register a
 callback for when the value arrives.
 
 It was pointed out that this is still possible with how the spec is
 now, but it will probably result in that developers will come up with
 conventions to set the result on the request themselves. This wouldn't
 be terribly bad, but also seems nice if we can help them.
 
 / Jonas
 
 On Mon, Jan 10, 2011 at 8:13 AM, ben turner bent.mozi...@gmail.com wrote:
 FWIW Jonas' proposed changes have been implemented and will be
 included in Firefox 4 Beta 9, due out in a few days.
 
 -Ben
 
 On Fri, Dec 10, 2010 at 12:47 PM, Jonas Sicking jo...@sicking.cc wrote:
 I've been reaching out to get feedback, but no success yet. Will re-poke.
 
 / Jonas
 
 On Fri, Dec 10, 2010 at 4:33 AM, Jeremy Orlow jor...@chromium.org wrote:
 Any additional thoughts on this?  If no one else cares, then we can go with
 Jonas' proposal (and we should file a bug).
 J
 
 On Thu, Nov 11, 2010 at 12:06 PM, Jeremy Orlow jor...@chromium.org wrote:
 
 On Tue, Nov 9, 2010 at 11:35 AM, Jonas Sicking jo...@sicking.cc wrote:
 
 Hi All,
 
 One of the things we briefly discussed at the summit was that we
 should make IDBErrorEvents have a .transaction. This since we are
 allowing you to place new requests from within error handlers, but we
 currently provide no way to get from an error handler to any useful
 objects. Instead developers will have to use closures to get to the
 transaction or other object stores.
 
 Another thing that is somewhat strange is that we only make the result
 available through the success event. There is no way after that to get
 it from the request. So instead we use special event interfaces with
 supply access to source, transaction and result.
 
 Compare this to how XMLHttpRequests work. Here the result and error
 code is available on the request object itself. The 'load' event,
 which is equivalent to our 'success' event didn't supply any
 information until we recently added progress event support. But still
 it only supplies information about the progress, not the actual value
 itself.
 
 One thing we could do is to move
 
 .source
 .transaction
 .result
 .error
 
 to IDBRequest. Then make success and error events be simple events
 which only implement the Event interface. I.e. we could get rid of the
 IDBEvent, IDBSuccessEvent, IDBTransactionEvent and IDBErrorEvent
 interfaces.
 
 We'd still have to keep IDBVersionChangeEvent, but it can inherit
 Event directly.
 
 The request created from IDBFactory.open would return a IDBRequest
 where .transaction and .source is null. We already fire a IDBEvent
 where .source is null (actually, the spec currently doesn't define
 what the source should be I see now).
 
 
 The only major downside with this setup that I can see is that the
 current syntax:
 
 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.result);
 }
 
 would turn into the slightly more verbose
 
 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.target.result);
 }
 
 (And note that with the error handling that we have discussed, the
 above code snippets are actually plausible (apart from the alert() of
 course)).
 
 The upside that I can see is that we behave more like XMLHttpRequest.
 It seems that people currently follow a coding pattern where they
 place a request and at some later point hand the request to another
 piece of code. At that point the code can either get the result from
 the .result property, or install a onload handler and wait for the
 result if it isn't yet available.
 
 However I only have anecdotal evidence that this is a common coding
 pattern, so not much to go on.
 
 Here's a counter proposal:  Let's add .transaction, .source, and .result
 to IDBEvent and just specify them to be null when there is no transaction,
 source, and/or result.  We then remove readyState from IDBResult as it
 serves no purpose.
 What I'm proposing would result in an API that's much more similar to what
 we have at the moment, but would be a bit different than XHR.  It is
 definitely good to have similar patterns for developers to follow, but I
 feel as thought the model of IndexedDB is already pretty different from 
 XHR.
  For example, method calls are supplied parameters and return an 
 IDBRequest
 object vs you using new 

Re: [IndexedDB] Events and requests

2011-01-10 Thread Keean Schupke
Okay, sorry, the original change seemed sensible, I guess I didn't see how
you got from there to promises.


Here's some fun to think about as an alternative though:


Interestingly the pattern of multiple callbacks, providing each callback is
passed zero or one parameter forms a Monad.

So for example if 'unit' is the constructor for the object returned from
get then onsuccess it 'bind' and I can show that these obey the 3 monad
laws. Allowing composability of callbacks. So you effectively have:

var x = db.transaction([foo]).objectStore(foo).getM(mykey);

var y =
db.transaction([foo]).objectStore(foo).getM(mykey1).bind(function(result1)
{

 db.transaction([foo]).objectStore(foo).getM(mykey2).bind(function(result2)
{
unit(result1 + result2);
});
});

The two objects returned x and y are both the same kind of object. y
represents the sum or concatination of the results of the lookups mykey1
and mykey2. You would use it identically to using the result of a single
lookup:

x.bind(function(result) {... display the result of a single lookup ...});

y.bind(function(result) {... display the result of both lookups ...});


If we could then have some syntactic sugar for this like haskell's do
notation we could write:

var y = do {
db.transaction([foo]).objectStore(foo).getM(mykey1);
result1 - db.transaction([foo]).objectStore(foo).getM(mykey2);
result2 - db.transaction([foo]).objectStore(foo).getM(mykey2);
unit(result1 + result2);
}

Which would be a very neat way of chaining callbacks...


Cheers,
Keean.


On 10 January 2011 22:00, Keean Schupke ke...@fry-it.com wrote:

 Whats wrong with callbacks? To me this seems an unnecessary complication.

 Presumably you would do:

 var promise = db.transaction([foo]).objectStore(foo).get(mykey);
 var result = promise.get();
 if (!result) {
 promise.onsuccess(function(res) {...X...});
 } else {
 ...Y...
 }


 So you end up having to duplicate code at X and Y to do the same thing
 directly or in the context of a callback. Or you define a function to
 process the result:

 var f = function(res) {...X...};
 var promise = db.transaction([foo]).objectStore(foo).get(mykey);
 var result = promise.get();
 if (!result) {
 promise.onsuccess(f);
 } else {
 f(result)
 };

 But in which case what advantage does all this extra clutter offer over:

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess(function(res)
 {...X...});


 I am just wondering whether the change is worth the added complexity?


 Cheers,
 Keean.


 On 10 January 2011 21:31, Jonas Sicking jo...@sicking.cc wrote:

 I did some outreach to developers and while I didn't get a lot of
 feedback, what I got was positive to this change.

 The basic use-case that was brought up was implementing a promises
 which, as I understand it, works similar to the request model I'm
 proposing. I.e. you build up these promise objects which represent a
 result which may or may not have arrived yet. At some point you can
 either read the value out, or if it hasn't arrived yet, register a
 callback for when the value arrives.

 It was pointed out that this is still possible with how the spec is
 now, but it will probably result in that developers will come up with
 conventions to set the result on the request themselves. This wouldn't
 be terribly bad, but also seems nice if we can help them.

 / Jonas

 On Mon, Jan 10, 2011 at 8:13 AM, ben turner bent.mozi...@gmail.com
 wrote:
  FWIW Jonas' proposed changes have been implemented and will be
  included in Firefox 4 Beta 9, due out in a few days.
 
  -Ben
 
  On Fri, Dec 10, 2010 at 12:47 PM, Jonas Sicking jo...@sicking.cc
 wrote:
  I've been reaching out to get feedback, but no success yet. Will
 re-poke.
 
  / Jonas
 
  On Fri, Dec 10, 2010 at 4:33 AM, Jeremy Orlow jor...@chromium.org
 wrote:
  Any additional thoughts on this?  If no one else cares, then we can go
 with
  Jonas' proposal (and we should file a bug).
  J
 
  On Thu, Nov 11, 2010 at 12:06 PM, Jeremy Orlow jor...@chromium.org
 wrote:
 
  On Tue, Nov 9, 2010 at 11:35 AM, Jonas Sicking jo...@sicking.cc
 wrote:
 
  Hi All,
 
  One of the things we briefly discussed at the summit was that we
  should make IDBErrorEvents have a .transaction. This since we are
  allowing you to place new requests from within error handlers, but
 we
  currently provide no way to get from an error handler to any useful
  objects. Instead developers will have to use closures to get to the
  transaction or other object stores.
 
  Another thing that is somewhat strange is that we only make the
 result
  available through the success event. There is no way after that to
 get
  it from the request. So instead we use special event interfaces with
  supply access to source, transaction and result.
 
  Compare this to how XMLHttpRequests work. Here the result and error
  code is available on the request object itself. The 'load' event,
  which is equivalent to our 'success' event didn't supply any
  

Re: [IndexedDB] Events and requests

2011-01-10 Thread Keean Schupke
Just to correct my cut and paste error, that was of course supposed to be:

var y = do {
result1 - db.transaction([foo]).objectStore(foo).getM(mykey1);
result2 - db.transaction([foo]).objectStore(foo).getM(mykey2);
unit(result1 + result2);
}


Cheers,
Keean.

On 10 January 2011 22:24, Keean Schupke ke...@fry-it.com wrote:

 Okay, sorry, the original change seemed sensible, I guess I didn't see how
 you got from there to promises.


 Here's some fun to think about as an alternative though:


 Interestingly the pattern of multiple callbacks, providing each callback is
 passed zero or one parameter forms a Monad.

 So for example if 'unit' is the constructor for the object returned from
 get then onsuccess it 'bind' and I can show that these obey the 3 monad
 laws. Allowing composability of callbacks. So you effectively have:

 var x = db.transaction([foo]).objectStore(foo).getM(mykey);

 var y =
 db.transaction([foo]).objectStore(foo).getM(mykey1).bind(function(result1)
 {

  
 db.transaction([foo]).objectStore(foo).getM(mykey2).bind(function(result2)
 {
 unit(result1 + result2);
 });
 });

 The two objects returned x and y are both the same kind of object. y
 represents the sum or concatination of the results of the lookups mykey1
 and mykey2. You would use it identically to using the result of a single
 lookup:

 x.bind(function(result) {... display the result of a single lookup ...});

 y.bind(function(result) {... display the result of both lookups ...});


 If we could then have some syntactic sugar for this like haskell's do
 notation we could write:

 var y = do {
 db.transaction([foo]).objectStore(foo).getM(mykey1);
 result1 - db.transaction([foo]).objectStore(foo).getM(mykey2);
 result2 - db.transaction([foo]).objectStore(foo).getM(mykey2);
 unit(result1 + result2);
 }

 Which would be a very neat way of chaining callbacks...


 Cheers,
 Keean.


 On 10 January 2011 22:00, Keean Schupke ke...@fry-it.com wrote:

 Whats wrong with callbacks? To me this seems an unnecessary complication.

 Presumably you would do:

 var promise = db.transaction([foo]).objectStore(foo).get(mykey);
 var result = promise.get();
 if (!result) {
 promise.onsuccess(function(res) {...X...});
 } else {
 ...Y...
 }


 So you end up having to duplicate code at X and Y to do the same thing
 directly or in the context of a callback. Or you define a function to
 process the result:

 var f = function(res) {...X...};
 var promise = db.transaction([foo]).objectStore(foo).get(mykey);
 var result = promise.get();
 if (!result) {
  promise.onsuccess(f);
 } else {
 f(result)
 };

 But in which case what advantage does all this extra clutter offer over:

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess(function(res)
 {...X...});


 I am just wondering whether the change is worth the added complexity?


 Cheers,
 Keean.


 On 10 January 2011 21:31, Jonas Sicking jo...@sicking.cc wrote:

 I did some outreach to developers and while I didn't get a lot of
 feedback, what I got was positive to this change.

 The basic use-case that was brought up was implementing a promises
 which, as I understand it, works similar to the request model I'm
 proposing. I.e. you build up these promise objects which represent a
 result which may or may not have arrived yet. At some point you can
 either read the value out, or if it hasn't arrived yet, register a
 callback for when the value arrives.

 It was pointed out that this is still possible with how the spec is
 now, but it will probably result in that developers will come up with
 conventions to set the result on the request themselves. This wouldn't
 be terribly bad, but also seems nice if we can help them.

 / Jonas

 On Mon, Jan 10, 2011 at 8:13 AM, ben turner bent.mozi...@gmail.com
 wrote:
  FWIW Jonas' proposed changes have been implemented and will be
  included in Firefox 4 Beta 9, due out in a few days.
 
  -Ben
 
  On Fri, Dec 10, 2010 at 12:47 PM, Jonas Sicking jo...@sicking.cc
 wrote:
  I've been reaching out to get feedback, but no success yet. Will
 re-poke.
 
  / Jonas
 
  On Fri, Dec 10, 2010 at 4:33 AM, Jeremy Orlow jor...@chromium.org
 wrote:
  Any additional thoughts on this?  If no one else cares, then we can
 go with
  Jonas' proposal (and we should file a bug).
  J
 
  On Thu, Nov 11, 2010 at 12:06 PM, Jeremy Orlow jor...@chromium.org
 wrote:
 
  On Tue, Nov 9, 2010 at 11:35 AM, Jonas Sicking jo...@sicking.cc
 wrote:
 
  Hi All,
 
  One of the things we briefly discussed at the summit was that we
  should make IDBErrorEvents have a .transaction. This since we are
  allowing you to place new requests from within error handlers, but
 we
  currently provide no way to get from an error handler to any useful
  objects. Instead developers will have to use closures to get to the
  transaction or other object stores.
 
  Another thing that is somewhat strange is that we only make the
 result
  available through the success 

Re: [IndexedDB] Events and requests

2011-01-10 Thread Jonas Sicking
This seems like something better suggeseted to the lists at ECMA where
javascript (or rather ECMAScript) is being standardized. I hardly
think that a database API like indexedDB is the place to redefine how
javascript should handle asynchronous programming.

/ Jonas

On Mon, Jan 10, 2011 at 2:26 PM, Keean Schupke ke...@fry-it.com wrote:
 Just to correct my cut and paste error, that was of course supposed to be:
 var y = do {
     result1 - db.transaction([foo]).objectStore(foo).getM(mykey1);
     result2 - db.transaction([foo]).objectStore(foo).getM(mykey2);
     unit(result1 + result2);
 }

 Cheers,
 Keean.
 On 10 January 2011 22:24, Keean Schupke ke...@fry-it.com wrote:

 Okay, sorry, the original change seemed sensible, I guess I didn't see how
 you got from there to promises.

 Here's some fun to think about as an alternative though:

 Interestingly the pattern of multiple callbacks, providing each callback
 is passed zero or one parameter forms a Monad.
 So for example if 'unit' is the constructor for the object returned from
 get then onsuccess it 'bind' and I can show that these obey the 3 monad
 laws. Allowing composability of callbacks. So you effectively have:
 var x = db.transaction([foo]).objectStore(foo).getM(mykey);
 var y =
 db.transaction([foo]).objectStore(foo).getM(mykey1).bind(function(result1)
 {

  db.transaction([foo]).objectStore(foo).getM(mykey2).bind(function(result2)
 {
         unit(result1 + result2);
     });
 });
 The two objects returned x and y are both the same kind of object. y
 represents the sum or concatination of the results of the lookups mykey1
 and mykey2. You would use it identically to using the result of a single
 lookup:
 x.bind(function(result) {... display the result of a single lookup ...});
 y.bind(function(result) {... display the result of both lookups ...});

 If we could then have some syntactic sugar for this like haskell's do
 notation we could write:
 var y = do {
     db.transaction([foo]).objectStore(foo).getM(mykey1);
     result1 - db.transaction([foo]).objectStore(foo).getM(mykey2);
     result2 - db.transaction([foo]).objectStore(foo).getM(mykey2);
     unit(result1 + result2);
 }
 Which would be a very neat way of chaining callbacks...

 Cheers,
 Keean.

 On 10 January 2011 22:00, Keean Schupke ke...@fry-it.com wrote:

 Whats wrong with callbacks? To me this seems an unnecessary complication.
 Presumably you would do:
 var promise = db.transaction([foo]).objectStore(foo).get(mykey);
 var result = promise.get();
 if (!result) {
     promise.onsuccess(function(res) {...X...});
 } else {
     ...Y...
 }

 So you end up having to duplicate code at X and Y to do the same thing
 directly or in the context of a callback. Or you define a function to
 process the result:
 var f = function(res) {...X...};
 var promise = db.transaction([foo]).objectStore(foo).get(mykey);
 var result = promise.get();
 if (!result) {
     promise.onsuccess(f);
 } else {
     f(result)
 };
 But in which case what advantage does all this extra clutter offer over:

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess(function(res)
 {...X...});

 I am just wondering whether the change is worth the added complexity?

 Cheers,
 Keean.

 On 10 January 2011 21:31, Jonas Sicking jo...@sicking.cc wrote:

 I did some outreach to developers and while I didn't get a lot of
 feedback, what I got was positive to this change.

 The basic use-case that was brought up was implementing a promises
 which, as I understand it, works similar to the request model I'm
 proposing. I.e. you build up these promise objects which represent a
 result which may or may not have arrived yet. At some point you can
 either read the value out, or if it hasn't arrived yet, register a
 callback for when the value arrives.

 It was pointed out that this is still possible with how the spec is
 now, but it will probably result in that developers will come up with
 conventions to set the result on the request themselves. This wouldn't
 be terribly bad, but also seems nice if we can help them.

 / Jonas

 On Mon, Jan 10, 2011 at 8:13 AM, ben turner bent.mozi...@gmail.com
 wrote:
  FWIW Jonas' proposed changes have been implemented and will be
  included in Firefox 4 Beta 9, due out in a few days.
 
  -Ben
 
  On Fri, Dec 10, 2010 at 12:47 PM, Jonas Sicking jo...@sicking.cc
  wrote:
  I've been reaching out to get feedback, but no success yet. Will
  re-poke.
 
  / Jonas
 
  On Fri, Dec 10, 2010 at 4:33 AM, Jeremy Orlow jor...@chromium.org
  wrote:
  Any additional thoughts on this?  If no one else cares, then we can
  go with
  Jonas' proposal (and we should file a bug).
  J
 
  On Thu, Nov 11, 2010 at 12:06 PM, Jeremy Orlow jor...@chromium.org
  wrote:
 
  On Tue, Nov 9, 2010 at 11:35 AM, Jonas Sicking jo...@sicking.cc
  wrote:
 
  Hi All,
 
  One of the things we briefly discussed at the summit was that we
  should make IDBErrorEvents have a .transaction. This since we are
  allowing you to place new 

Re: [IndexedDB] Events and requests

2011-01-10 Thread Axel Rauschmayer
Coming back to the initial message in this thread (at the very bottom):
= General rule of thumb: clearly separate input data and output data.

Using JavaScript dynamic nature, things could look as follows:

indexedDB.open('AddressBook', 'Address Book', {
success: function(evt) {
},
error: function(evt) {
}
});

- The last argument is thus the request and clearly input.

- If multiple success handlers are needed, success could be an array of 
functions (same for error handlers).

- I would eliminiate readyState and move abort() to IDBEvent (=output and an 
interface to the DB client).

- With subclasses of IDBEvent one has the choice of eliminating them by making 
their fields additional parameters of success() and error(). event.result is a 
prime candidate for this!

- This above way eliminates the need of manipulating the request *after* (a 
reference to) it has been placed in the event queue.

Questions:

- Is it really necessary to make IDBEvent a subclass of Event and thus drag the 
DOM (which seems to be universally hated) into IndexedDB?

- Are there any other asynchronous DB APIs for dynamic languages that one could 
learn from (especially from mistakes that they have made)? They must have 
design principles and rationales one might be able to use. WebDatabase (minus 
schema plus cursor) looks nice.

On Jan 10, 2011, at 23:40 , Keean Schupke wrote:

 Hi, 
 
 I did say it was for fun!  If you think it should be suggested somewhere I am 
 happy to do so. Note that  I renamed 'onsuccess' to 'bind' to show how it 
 works as a monad, there is no need to do this (although I prefer to it to 
 explicitly show it is a Monad).
 
 The definition of unit is simply:
 
 var unit = function(v) {
 return {
 onsuccess: function(f) {f(v);}
 };
 };
 
 And then you can compose callbacks using 'onsuccess'...
 
 you might like to keep onsuccess, and use result instead of unit... So 
 simply using the above definition you can compose callbacks:
 
 var y = 
 db.transaction([foo]).objectStore(foo).getM(mykey1).onsuccess(function(result1)
  {
 
 db.transaction([foo]).objectStore(foo).getM(mykey2).onsuccess(function(result2)
  {
 result(result1 + result2);
 });
 }); 
 
 
 Cheers,
 Keean.
 
 
 On 10 January 2011 22:31, Jonas Sicking jo...@sicking.cc wrote:
 This seems like something better suggeseted to the lists at ECMA where
 javascript (or rather ECMAScript) is being standardized. I hardly
 think that a database API like indexedDB is the place to redefine how
 javascript should handle asynchronous programming.
 
 / Jonas
 
 On Mon, Jan 10, 2011 at 2:26 PM, Keean Schupke ke...@fry-it.com wrote:
  Just to correct my cut and paste error, that was of course supposed to be:
  var y = do {
  result1 - db.transaction([foo]).objectStore(foo).getM(mykey1);
  result2 - db.transaction([foo]).objectStore(foo).getM(mykey2);
  unit(result1 + result2);
  }
 
  Cheers,
  Keean.
  On 10 January 2011 22:24, Keean Schupke ke...@fry-it.com wrote:
 
  Okay, sorry, the original change seemed sensible, I guess I didn't see how
  you got from there to promises.
 
  Here's some fun to think about as an alternative though:
 
  Interestingly the pattern of multiple callbacks, providing each callback
  is passed zero or one parameter forms a Monad.
  So for example if 'unit' is the constructor for the object returned from
  get then onsuccess it 'bind' and I can show that these obey the 3 monad
  laws. Allowing composability of callbacks. So you effectively have:
  var x = db.transaction([foo]).objectStore(foo).getM(mykey);
  var y =
  db.transaction([foo]).objectStore(foo).getM(mykey1).bind(function(result1)
  {
 
   
  db.transaction([foo]).objectStore(foo).getM(mykey2).bind(function(result2)
  {
  unit(result1 + result2);
  });
  });
  The two objects returned x and y are both the same kind of object. y
  represents the sum or concatination of the results of the lookups mykey1
  and mykey2. You would use it identically to using the result of a single
  lookup:
  x.bind(function(result) {... display the result of a single lookup ...});
  y.bind(function(result) {... display the result of both lookups ...});
 
  If we could then have some syntactic sugar for this like haskell's do
  notation we could write:
  var y = do {
  db.transaction([foo]).objectStore(foo).getM(mykey1);
  result1 - db.transaction([foo]).objectStore(foo).getM(mykey2);
  result2 - db.transaction([foo]).objectStore(foo).getM(mykey2);
  unit(result1 + result2);
  }
  Which would be a very neat way of chaining callbacks...
 
  Cheers,
  Keean.
 
  On 10 January 2011 22:00, Keean Schupke ke...@fry-it.com wrote:
 
  Whats wrong with callbacks? To me this seems an unnecessary complication.
  Presumably you would do:
  var promise = db.transaction([foo]).objectStore(foo).get(mykey);
  var result = promise.get();
  if (!result) {
  promise.onsuccess(function(res) {...X...});
  } else {
  

Re: [IndexedDB] Events and requests

2010-12-10 Thread Jeremy Orlow
Any additional thoughts on this?  If no one else cares, then we can go with
Jonas' proposal (and we should file a bug).

J

On Thu, Nov 11, 2010 at 12:06 PM, Jeremy Orlow jor...@chromium.org wrote:

 On Tue, Nov 9, 2010 at 11:35 AM, Jonas Sicking jo...@sicking.cc wrote:

 Hi All,

 One of the things we briefly discussed at the summit was that we
 should make IDBErrorEvents have a .transaction. This since we are
 allowing you to place new requests from within error handlers, but we
 currently provide no way to get from an error handler to any useful
 objects. Instead developers will have to use closures to get to the
 transaction or other object stores.

 Another thing that is somewhat strange is that we only make the result
 available through the success event. There is no way after that to get
 it from the request. So instead we use special event interfaces with
 supply access to source, transaction and result.

 Compare this to how XMLHttpRequests work. Here the result and error
 code is available on the request object itself. The 'load' event,
 which is equivalent to our 'success' event didn't supply any
 information until we recently added progress event support. But still
 it only supplies information about the progress, not the actual value
 itself.

 One thing we could do is to move

 .source
 .transaction
 .result
 .error

 to IDBRequest. Then make success and error events be simple events
 which only implement the Event interface. I.e. we could get rid of the
 IDBEvent, IDBSuccessEvent, IDBTransactionEvent and IDBErrorEvent
 interfaces.

 We'd still have to keep IDBVersionChangeEvent, but it can inherit
 Event directly.

 The request created from IDBFactory.open would return a IDBRequest
 where .transaction and .source is null. We already fire a IDBEvent
 where .source is null (actually, the spec currently doesn't define
 what the source should be I see now).


 The only major downside with this setup that I can see is that the
 current syntax:

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.result);
 }

 would turn into the slightly more verbose

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.target.result);
 }

 (And note that with the error handling that we have discussed, the
 above code snippets are actually plausible (apart from the alert() of
 course)).

 The upside that I can see is that we behave more like XMLHttpRequest.
 It seems that people currently follow a coding pattern where they
 place a request and at some later point hand the request to another
 piece of code. At that point the code can either get the result from
 the .result property, or install a onload handler and wait for the
 result if it isn't yet available.

 However I only have anecdotal evidence that this is a common coding
 pattern, so not much to go on.


 Here's a counter proposal:  Let's add .transaction, .source, and .result to
 IDBEvent and just specify them to be null when there is no transaction,
 source, and/or result.  We then remove readyState from IDBResult as it
 serves no purpose.

 What I'm proposing would result in an API that's much more similar to what
 we have at the moment, but would be a bit different than XHR.  It is
 definitely good to have similar patterns for developers to follow, but I
 feel as thought the model of IndexedDB is already pretty different from XHR.
  For example, method calls are supplied parameters and return an IDBRequest
 object vs you using new to create the XHR object and then making method
 calls to set it up and then making a method call to start it.  In fact, if
 you think about it, there's really not that much XHR and IndexedDB have in
 common except that they use event handlers.

 As for your proposal, let me think about it for a bit and forward it on to
 some people I know who are playing with IndexedDB already.

 J



Re: [IndexedDB] Events and requests

2010-12-10 Thread Jonas Sicking
I've been reaching out to get feedback, but no success yet. Will re-poke.

/ Jonas

On Fri, Dec 10, 2010 at 4:33 AM, Jeremy Orlow jor...@chromium.org wrote:
 Any additional thoughts on this?  If no one else cares, then we can go with
 Jonas' proposal (and we should file a bug).
 J

 On Thu, Nov 11, 2010 at 12:06 PM, Jeremy Orlow jor...@chromium.org wrote:

 On Tue, Nov 9, 2010 at 11:35 AM, Jonas Sicking jo...@sicking.cc wrote:

 Hi All,

 One of the things we briefly discussed at the summit was that we
 should make IDBErrorEvents have a .transaction. This since we are
 allowing you to place new requests from within error handlers, but we
 currently provide no way to get from an error handler to any useful
 objects. Instead developers will have to use closures to get to the
 transaction or other object stores.

 Another thing that is somewhat strange is that we only make the result
 available through the success event. There is no way after that to get
 it from the request. So instead we use special event interfaces with
 supply access to source, transaction and result.

 Compare this to how XMLHttpRequests work. Here the result and error
 code is available on the request object itself. The 'load' event,
 which is equivalent to our 'success' event didn't supply any
 information until we recently added progress event support. But still
 it only supplies information about the progress, not the actual value
 itself.

 One thing we could do is to move

 .source
 .transaction
 .result
 .error

 to IDBRequest. Then make success and error events be simple events
 which only implement the Event interface. I.e. we could get rid of the
 IDBEvent, IDBSuccessEvent, IDBTransactionEvent and IDBErrorEvent
 interfaces.

 We'd still have to keep IDBVersionChangeEvent, but it can inherit
 Event directly.

 The request created from IDBFactory.open would return a IDBRequest
 where .transaction and .source is null. We already fire a IDBEvent
 where .source is null (actually, the spec currently doesn't define
 what the source should be I see now).


 The only major downside with this setup that I can see is that the
 current syntax:

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.result);
 }

 would turn into the slightly more verbose

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.target.result);
 }

 (And note that with the error handling that we have discussed, the
 above code snippets are actually plausible (apart from the alert() of
 course)).

 The upside that I can see is that we behave more like XMLHttpRequest.
 It seems that people currently follow a coding pattern where they
 place a request and at some later point hand the request to another
 piece of code. At that point the code can either get the result from
 the .result property, or install a onload handler and wait for the
 result if it isn't yet available.

 However I only have anecdotal evidence that this is a common coding
 pattern, so not much to go on.

 Here's a counter proposal:  Let's add .transaction, .source, and .result
 to IDBEvent and just specify them to be null when there is no transaction,
 source, and/or result.  We then remove readyState from IDBResult as it
 serves no purpose.
 What I'm proposing would result in an API that's much more similar to what
 we have at the moment, but would be a bit different than XHR.  It is
 definitely good to have similar patterns for developers to follow, but I
 feel as thought the model of IndexedDB is already pretty different from XHR.
  For example, method calls are supplied parameters and return an IDBRequest
 object vs you using new to create the XHR object and then making method
 calls to set it up and then making a method call to start it.  In fact, if
 you think about it, there's really not that much XHR and IndexedDB have in
 common except that they use event handlers.
 As for your proposal, let me think about it for a bit and forward it on to
 some people I know who are playing with IndexedDB already.
 J




Re: [IndexedDB] Events and requests

2010-11-11 Thread Jeremy Orlow
On Tue, Nov 9, 2010 at 11:35 AM, Jonas Sicking jo...@sicking.cc wrote:

 Hi All,

 One of the things we briefly discussed at the summit was that we
 should make IDBErrorEvents have a .transaction. This since we are
 allowing you to place new requests from within error handlers, but we
 currently provide no way to get from an error handler to any useful
 objects. Instead developers will have to use closures to get to the
 transaction or other object stores.

 Another thing that is somewhat strange is that we only make the result
 available through the success event. There is no way after that to get
 it from the request. So instead we use special event interfaces with
 supply access to source, transaction and result.

 Compare this to how XMLHttpRequests work. Here the result and error
 code is available on the request object itself. The 'load' event,
 which is equivalent to our 'success' event didn't supply any
 information until we recently added progress event support. But still
 it only supplies information about the progress, not the actual value
 itself.

 One thing we could do is to move

 .source
 .transaction
 .result
 .error

 to IDBRequest. Then make success and error events be simple events
 which only implement the Event interface. I.e. we could get rid of the
 IDBEvent, IDBSuccessEvent, IDBTransactionEvent and IDBErrorEvent
 interfaces.

 We'd still have to keep IDBVersionChangeEvent, but it can inherit
 Event directly.

 The request created from IDBFactory.open would return a IDBRequest
 where .transaction and .source is null. We already fire a IDBEvent
 where .source is null (actually, the spec currently doesn't define
 what the source should be I see now).


 The only major downside with this setup that I can see is that the
 current syntax:

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.result);
 }

 would turn into the slightly more verbose

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
  alert(e.target.result);
 }

 (And note that with the error handling that we have discussed, the
 above code snippets are actually plausible (apart from the alert() of
 course)).

 The upside that I can see is that we behave more like XMLHttpRequest.
 It seems that people currently follow a coding pattern where they
 place a request and at some later point hand the request to another
 piece of code. At that point the code can either get the result from
 the .result property, or install a onload handler and wait for the
 result if it isn't yet available.

 However I only have anecdotal evidence that this is a common coding
 pattern, so not much to go on.


Here's a counter proposal:  Let's add .transaction, .source, and .result to
IDBEvent and just specify them to be null when there is no transaction,
source, and/or result.  We then remove readyState from IDBResult as it
serves no purpose.

What I'm proposing would result in an API that's much more similar to what
we have at the moment, but would be a bit different than XHR.  It is
definitely good to have similar patterns for developers to follow, but I
feel as thought the model of IndexedDB is already pretty different from XHR.
 For example, method calls are supplied parameters and return an IDBRequest
object vs you using new to create the XHR object and then making method
calls to set it up and then making a method call to start it.  In fact, if
you think about it, there's really not that much XHR and IndexedDB have in
common except that they use event handlers.

As for your proposal, let me think about it for a bit and forward it on to
some people I know who are playing with IndexedDB already.

J


Re: [IndexedDB] Events and requests

2010-11-10 Thread Shawn Wilsher

On 11/9/2010 12:35 AM, Jonas Sicking wrote:

One thing we could do is to move

.source
.transaction
.result
.error

to IDBRequest. Then make success and error events be simple events
which only implement the Event interface. I.e. we could get rid of the
IDBEvent, IDBSuccessEvent, IDBTransactionEvent and IDBErrorEvent
interfaces.

We'd still have to keep IDBVersionChangeEvent, but it can inherit
Event directly.

The request created from IDBFactory.open would return a IDBRequest
where .transaction and .source is null. We already fire a IDBEvent
where .source is null (actually, the spec currently doesn't define
what the source should be I see now).

This seems fine to me.


db.transaction([foo]).objectStore(foo).get(mykey).onsuccess = function(e) {
   alert(e.result);
}

would turn into the slightly more verbose

db.transaction([foo]).objectStore(foo).get(mykey).onsuccess = function(e) {
   alert(e.target.result);
}
The only difference is e.result vs e.target.result, right?  I'm not sure 
we should worry about that little bit (and consumers can always use a 
local variable for that if it bothers them).


Cheers,

Shawn



smime.p7s
Description: S/MIME Cryptographic Signature


Re: [IndexedDB] Events and requests

2010-11-10 Thread Jonas Sicking
On Wed, Nov 10, 2010 at 10:38 AM, Shawn Wilsher sdwi...@mozilla.com wrote:
 On 11/9/2010 12:35 AM, Jonas Sicking wrote:

 One thing we could do is to move

 .source
 .transaction
 .result
 .error

 to IDBRequest. Then make success and error events be simple events
 which only implement the Event interface. I.e. we could get rid of the
 IDBEvent, IDBSuccessEvent, IDBTransactionEvent and IDBErrorEvent
 interfaces.

 We'd still have to keep IDBVersionChangeEvent, but it can inherit
 Event directly.

 The request created from IDBFactory.open would return a IDBRequest
 where .transaction and .source is null. We already fire a IDBEvent
 where .source is null (actually, the spec currently doesn't define
 what the source should be I see now).

 This seems fine to me.

Cool.

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
   alert(e.result);
 }

 would turn into the slightly more verbose

 db.transaction([foo]).objectStore(foo).get(mykey).onsuccess =
 function(e) {
   alert(e.target.result);
 }

 The only difference is e.result vs e.target.result, right?  I'm not sure we
 should worry about that little bit (and consumers can always use a local
 variable for that if it bothers them).

Yes, that's the only difference.

/ Jonas