Welcome, guest ( Login )

WikiHome » dojo.data » Dojo Data Meetings » 2006-09-26

2006-09-26

Version 19, changed by brian 09/26/2006.   Show version history

Agenda

  • dojo.data.Result API
    1. change the name of our forEach() method, or chance the signature to match the array iterator in JS 1.6: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
      • ignore the return value of the callback function (rather than assuming a boolean return value, with false meaning cancel loop)?
    2. signature of errback, (& use for timeout?)
    3. errbacks and callbacks
      • addCallback(foo); When is foo called? When forEach() loop has completed? When some data is loaded, available for looping over? When all data is loaded?
      • can errbacks and callbacks be chained, as with Deferred objects? Seems like a lot to ask of simple dojo.data.Result implementations.
      • can we pass a controller object?
        • result.addCallback(callback);
        • result.addCallback(object, "callback"); // dojo.event.connect() style
        • result.addCallback(object.callback, object); // Array.forEach() style
    4. result.cancel() cancels everything (request, other pending callbacks) not just current iteration ?
    5. clarify: run multiple foreachs run serially not in parallel?
    6. what does inProgress() mean?
      • forEach() loop is in progress?
      • data is loading (query has been sent, forEach() not yet called)?
      • either of the above?
  • dojo.data.Read API
    1. get() returns undefined if attribute is present but has no values?
    2. getValues() returns [] if attribute is present but has no values?
    3. remove hasAttributeValue()?
    4. change getByIdentity() to findByIdentity(), as per suggestion in mail from Adam Souzis?
    5. findByIdentity() always synchronous?
    6. move getIdentity() and findByIdentity() out of dojo.data.Read (maybe into dojo.data.Identity)?
    7. have findByIdentity() return null if no item is found, rather than throwing an excpetion?
    8. find(query, {async:true}) vs. find(query, {sync:false})
      • just support 'async', or just 'sync', or both?
      • default to {async:false}?
    9. semantics of isItem() more like isItemAvailable() (and, if so, rename it)?
      • should isItem(x) return true if x is an item Identity instead of an item?
      • should isItem(x) return true if x is an item that has been deleted? Prior to a save? After a save?
  • dojo.data.Write API
    1. save()
      • store.save({async: true})?
      • store.save({async: true, onComplete: callback});
      • always return a Deferred, or sometimes a boolean?
      • default to sync, not async?
    2. include methods add() and remove()
      • store.set(kermit, color, "green");
      • store.add(kermit, color, "blue");
      • store.add(kermit, color, "aqua", {at: 0});
      • store.add(kermit, color, "cyan", {after: "blue"});
      • store.remove(kermit, color, "green");
    3. should isDirty() with no args returns whether the current transaction is dirty?
    4. should dojo.data.Write include (extend) dojo.data.Read?
  • add new code (where?, minor code style stuff first?)
    1. check in RemoteStore?
    2. check in mockXmlHttpRequest?
    3. move dojo.data.csv.Result out of .csv, for re-use?
  • wait to sign off on some APIs (Read/Result/Write) until after we have some lessons learned from trying initial implementations?

Resolutions

  • dojo.data.Result API
    1. we will make the signature of our result.forEach() be compatible with the signature of the array iterator in JS 1.6: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
      • examples:
        • result.forEach(someCallbackFunction)
        • result.forEach(someObject.someCallbackMethod, someObject)
        • result.forEach(obj.callback, obj, {foo:100, bar:true});
        • result.forEach(callbackFunc, null, {foo:100, bar:true});
      • also, we will ignore the return value of the callback function (rather than assuming a boolean return value, with false meaning cancel loop)
    2. If there's an error, we will pass an Error object to whatever error callback function that the user set:
      • someErrorHandler(/ Error / error) { / deal with it / }
    3. errbacks and callbacks
      • Result objects will not provide any features for "chaining" errbacks and callbacks. We won't provide API for you to "add" errbacks and callbacks, just "set" errbacks and callbacks.
      • We will change the names of the methods, to try to better describe what they do:
        • setOnError()
        • setOnFindCompleted()
      • The caller can either set a simple callback function or set a function on some handler object. We will use the same syntax here as we do on forEach()
        • setOnError(someCallbackFunction)
        • setOnError(someObject.someCallbackMethod, someObject)
        • setOnFindCompleted(someCallbackFunction)
        • setOnFindCompleted(someObject.someCallbackMethod, someObject)
      • With setOnFindCompleted(foo), foo will be called when find() call has finished loading all the found data.
    4. result.cancel() cancels everything it can. It cancels the current forEach() loop, aborts the XmlHttpRequest, cancels error callbacks, cancels the OnFindCompleted callback, etc.


Transcript

[1:11 PM] brian_skinner: shall we get started?
[1:12 PM] aszs: ok
[1:12 PM] brian_skinner: agenda -- http://dojo.jot.com/2006-09-26
[1:13 PM] aszs: let's go through them 1 by 1?
[1:13 PM] brian_skinner: i've got no preference about the order -- feel free to cherry-pick -- or we could just start from the top
[1:13 PM] jaxsphere__: forEach?
[1:13 PM] brian_skinner: forEach
[1:13 PM] aszs: +1 to match 1.6
[1:13 PM] aszs: signature
[1:13 PM] brian_skinner: fine by me
[1:13 PM] aszs: +.05 to ignore return value
[1:14 PM] brian_skinner: +1 to ignore return value -- that was going to be a pain anyway, and it doesn't match 1.6
[1:14 PM] brian_skinner: match 1.6, but maybe with an optional 3rd argument?
[1:14 PM] brian_skinner: forEach(callback)
[1:15 PM] brian_skinner: forEach(callback, thisObject)
[1:15 PM] brian_skinner: forEach(callback, thisObject, {start:100, end:300});
[1:16 PM] brian_skinner: maybe not *start* and *end*, but potentionally some optional keyword args
[1:16 PM] aszs: ok
[1:16 PM] brian_skinner: i've never used that 1.6 style of object callback
[1:16 PM] brian_skinner: does that just work
[1:16 PM] brian_skinner: forEach(this.callback, this);
[1:17 PM] brian_skinner: ?
[1:17 PM] aszs: u mean this.foo instead of "foo"?
[1:17 PM] brian_skinner: aszs: right
[1:17 PM] aszs: sure
[1:17 PM] brian_skinner: cool
[1:17 PM] jaxsphere__: +1 match 1.6
[1:18 PM] brian_skinner: resolved.
[1:18 PM] brian_skinner: next
[1:18 PM] aszs: let's talk about #4
[1:18 PM] aszs: its related to the return value
[1:18 PM] brian_skinner: okay
[1:18 PM] aszs: for foreach
[1:18 PM] aszs: result.cancel()
[1:18 PM] aszs: my implementation has it cancel everything
[1:19 PM] aszs: if async io is still happening it calls abort
[1:19 PM] brian_skinner: cancels any related XmlHttpRequest?
[1:19 PM] aszs: yes
[1:19 PM] aszs: i think that the way it should work
[1:19 PM] brian_skinner: fine by me
[1:20 PM] brian_skinner: jaxsphere__?
[1:20 PM] aszs: but then how to say just cancel this iteration if we drop the return value thing
[1:20 PM] brian_skinner: maybe it's not important to cancel just this iteration?
[1:20 PM] aszs: maybe
[1:21 PM] aszs: i'm fine punting for now
[1:21 PM] brian_skinner: client code could always continue the iteration and just no-op in each callback
[1:21 PM] aszs: yes
[1:21 PM] brian_skinner: or we could let cancel() take some parameter
[1:21 PM] aszs: hmm, i don't like that
[1:22 PM] aszs: lets just skip that "feature"
[1:22 PM] brian_skinner: okay, well we could always add another method later, or add a parameter later
[1:22 PM] brian_skinner: for now just have a simple cancel that cancels everything
[1:22 PM] aszs: +1
[1:22 PM] brian_skinner: +0
[1:22 PM] jaxsphere__: cancel everything, eg. abort XHR & iter, right?
[1:22 PM] brian_skinner: (fine with anything)
[1:22 PM] aszs: yes
[1:22 PM] jaxsphere__: +1
[1:23 PM] brian_skinner: resolved.
[1:23 PM] brian_skinner: next
[1:23 PM] aszs: lets go back to 2?
[1:23 PM] brian_skinner: okay
[1:23 PM] aszs: errback(Error)?
[1:24 PM] aszs: i don't know dojo policies on exceptions
[1:24 PM] aszs: just uses Error with different string messages?
[1:24 PM] jaxsphere__: looking at bind
[1:24 PM] brian_skinner: hmm.. maybe we should back up to a bigger question for a second
[1:25 PM] brian_skinner: i want to question whether we really want to match the Deferred method signatures for addCallback and addErrback
[1:25 PM] aszs: bind uses Error
[1:25 PM] aszs: ok
[1:25 PM] brian_skinner: but if we do want to match Deferred, then doesn't that dictate what the errback() signature is?
[1:26 PM] aszs: i pretty sure its errback(Error)
[1:26 PM] jaxsphere__: 			var errObj = new dojo.io.Error("XMLHttpTransport Error: "+http.status+" "+http.statusText);
[1:26 PM] dmachi: deferred creates an Error object if you pass it something that isn't an error object
[1:28 PM] brian_skinner: would it be useful to also pass the result object?  --  errback(Error, result)?
[1:28 PM] aszs: i don't think so, just use a closures
[1:28 PM] aszs: +1 for errback(Error)
[1:28 PM] brian_skinner: on the bigger picture question, i have three reservactions...
[1:29 PM] dmachi: in rpc, where you could ahve an "error" reported fromt he server _or_ a transport error
[1:29 PM] dmachi: both going tot he same errback i basically created an Error object, then copied over the additional properties from the RPC error that were missing
[1:29 PM] dmachi: (message, id, etc)
[1:29 PM] dmachi: by defaul, if you do something like errback(myresult)
[1:29 PM] jaxsphere__: nested errors
[1:29 PM] jaxsphere__: ?
[1:30 PM] dmachi: it will try to toString() myresult and shove it in the Message property of the Error object
[1:31 PM] brian_skinner: reservation one:  I hope to have a lot of datastore implementations, so I want to make it easy to implement these APIs -- addCallback() and addErrback() allow for chains of callbacks, which seems unnecessary here, and requires work to implement
[1:31 PM] dmachi: so basically errback(someObj) check to see if its an Error object, if so it passes it along to you error callback methods, otherwise it tries to convert it (not too wel) to an error object.
[1:32 PM] brian_skinner: reservation two: when you addCallback(foo), I think it's not clear when foo will be called, and the name "addCallback" does nothing to clarify
[1:32 PM] dmachi: why isn't it clear?  It will be called when the callback is called
[1:33 PM] aszs: if addCallback matches deferred semantics it will fire when the event has completed
[1:33 PM] aszs: inProgress() == false
[1:33 PM] aszs: forEachcallback already fired
[1:33 PM] brian_skinner: reservation three: I think most of the time, you're going to want to call the callback and errback methods of some particular UI controller object, so it would be nice if you could just register the callback that way in the first place
[1:33 PM] dmachi: note that i'm not trying to push deferreds on this dojo.data stuff i'm just trying to help clarify
[1:34 PM] aszs: brian: not sure understand #3
[1:34 PM] brian_skinner: callback could be called: (a) when some data is available, so you can start a forEach loop, (b) when all data is available, (c) when a forEach loop has just finished
[1:35 PM] dmachi: just as a side note the project i'm working on now basically is a non-standarized data provider and i use deferreds all over the place with good success.
[1:35 PM] brian_skinner: dmachi: yup, thanks for being here to explain how the deferred work -- i've never used them
[1:35 PM] aszs: its (b)
[1:36 PM] aszs: we could call it oncompletion
[1:36 PM] brian_skinner: aszs: #3 example -- want to do result.addCallback(controllerObj.callback, controllerObj) rather than result.addCallback(callback)
[1:36 PM] dmachi: you can currently do addCallback(controllerObj, "callback")
[1:36 PM] brian_skinner: (b) is fine with me, but I don't think the name "callback" makes it clear that (b) is when we're calling
[1:37 PM] aszs: hmm, i'd like to match forEach signature
[1:37 PM] aszs: i'm ok with changing the name
[1:37 PM] brian_skinner: dmachi: ah, okay, then my reservation #3 goes away
[1:37 PM] aszs: agnostic about chaining
[1:38 PM] aszs: fyi: 	addCallback:
[1:38 PM] aszs: 		function( callbackFunction) {
[1:38 PM] aszs: 		    this._callBacks.push(callbackFunction);
[1:38 PM] aszs: 		    if (this.data)  //already fired
[1:38 PM] aszs: 		        callbackFunction(this.data);
[1:38 PM] dmachi: i've not really been followign the forEach discussion, but are you gusy wanting to retive a whole bunch of data then iterate over it?>
[1:38 PM] aszs: 		},
[1:38 PM] aszs: that's my impl. of addCallback in RemoteStore
[1:38 PM] brian_skinner: dmachi: yup, just iterating over a list of items
[1:38 PM] dmachi: so each item is retrieved separately?
[1:39 PM] jaxsphere__: or in chuncks
[1:39 PM] brian_skinner: aszs: that implementation doesn't do the whole chaining thing, does it?
[1:39 PM] dmachi: so in my code where i have to do that, i use Deferred for each "chunk", and a deferred list which makes sure all the chunks have come back
[1:39 PM] dmachi: if that is of any help in this discussion.
[1:40 PM] brian_skinner: aszs: or, put another way, there's some more implementation elsewhere that does the chaining
[1:40 PM] aszs: that happens in the find handler:
[1:40 PM] aszs:                                 result._forEachCallBacks = [];
[1:40 PM] aszs:                                 for (var i = 0; i < result._callBacks.length; i++) {
[1:40 PM] aszs:                                     if (result._aborted)
[1:40 PM] aszs:                                         break;
[1:40 PM] aszs:                                     result._callBacks[i](resultData);
[1:40 PM] aszs:                                 }
[1:40 PM] aszs:                                 result._callBacks = [];
[1:40 PM] dmachi: so deferred list itself takes an array of deferreds, and when they have all called back, it will fire the deferredlists' callback
[1:41 PM] aszs: note: that you can chain forEach's too
[1:41 PM] brian_skinner: aszs: I think that implementation may not be quite right -- don't you need to take the result of one callback and pass it to the next callback in the chain?
[1:41 PM] aszs: oh, if that's what you want i'm -1 on that
[1:41 PM] aszs: kind of chaining
[1:42 PM] brian_skinner: well, it's not what I want, but if we really are trying to match the semantics of the Deferred object
[1:42 PM] aszs: so now i'm convinced to change the name of addCallBack
[1:42 PM] brian_skinner: i'd rather not try to match the semantics of Deferred
[1:43 PM] aszs: ok
[1:44 PM] aszs: so what gets passed in Deferred?
[1:44 PM] aszs: an iterator?
[1:44 PM] aszs: an array?
[1:45 PM] brian_skinner: so, i propose: (1) change the name of addCallback, (2) drop the notion of chaining, and just allow a single callback, and (3) for the case where you pass an object and a callback method, we match the syntax of forEach rather than the syntax of Deferred and dojo.event.connect
[1:45 PM] brian_skinner: aszs: sorry, don't understand the question
[1:45 PM] aszs: callback(result) -- what result?
[1:45 PM] aszs: i pass an array of "item"s
[1:45 PM] brian_skinner: the return value of the previous callback
[1:46 PM] aszs: no, not with chaining
[1:46 PM] brian_skinner: callback3(callback2(callback1(result)))
[1:46 PM] aszs: what's result?
[1:46 PM] brian_skinner: oh, i see
[1:46 PM] brian_skinner: um, no result?
[1:46 PM] brian_skinner: callback()
[1:47 PM] aszs: i say an array of items
[1:47 PM] brian_skinner: an array of all 1,000 items?
[1:47 PM] aszs: that's not very useful
[1:47 PM] aszs: an iterator
[1:47 PM] aszs: of 1000 items
[1:47 PM] brian_skinner: isn't that why we have forEach()
[1:47 PM] brian_skinner: to avoid that nasty iterator syntax we were experimenting with?
[1:48 PM] brian_skinner: I think callback() does have some value, with no parameter
[1:48 PM] aszs: some value?
[1:48 PM] brian_skinner: it lets the UI know that it shouldn't expect more forEach() looping
[1:49 PM] brian_skinner: so the UI can stop displaying a "Loading" cursor
[1:49 PM] brian_skinner: for example
[1:49 PM] brian_skinner: or the UI can do final calculations about the size of the scroll bar
[1:49 PM] brian_skinner: or whatever
[1:50 PM] brian_skinner: oh wait...
[1:50 PM] aszs: i say we just pass in dojo.collection.Iterator
[1:51 PM] aszs: the nastiness isn't there
[1:51 PM] aszs: its was when we thinking about async, etc.
[1:51 PM] brian_skinner: i was thinking of a callback that happens on (c) the end of forEach looping, but we just said it happens on (b) all data available for looping -- oops
[1:51 PM] aszs: just ignore it
[1:52 PM] aszs: but yes after foreach
[1:52 PM] aszs: protocol: as data is receved invoke foreach
[1:52 PM] aszs: when done invoke callback
[1:52 PM] aszs: but if foreach is called after data is recieved
[1:53 PM] aszs: callback isn't called again
[1:53 PM] brian_skinner: then what problem does passing an iterator solve -- aren't we using forEach for looping, not the iterator
[1:54 PM] aszs: if just want to look at the results its pretty annoying to have to call foreach and build your own array
[1:54 PM] aszs: the implementation has to have that info anyway
[1:55 PM] aszs: because we support calling foreach multiple times
[1:55 PM] aszs: its trival to implement and doesn't cost anything and is quite useful in some cases
[1:55 PM] brian_skinner: i think if you just want an array, then we should just have a method that returns an array -- findArray() -- rather than something that returns an iterator
[1:56 PM] brian_skinner: but, why do you want to build your own array?
[1:57 PM] aszs: well i have to because the only way i can get the results is through foreach
[1:57 PM] aszs: a lot of times what we do with the results is not something incremental and stateless
[1:58 PM] aszs: so putting the functionality in a foreach callback is cumbersome
[1:58 PM] aszs: say you need to look forward and back at the results
[1:58 PM] aszs: or just check for a particular value
[1:59 PM] brian_skinner: but then an iterator doesn't help either, right?
[2:00 PM] brian_skinner: i think I need a concrete example in order to understand
[2:00 PM] aszs: it does: you have all results avaible right there...
[2:01 PM] brian_skinner: displaying a list of items in a table view?
[2:01 PM] aszs: for (int i =0; i < resultarray.length(); i++)
[2:01 PM] brian_skinner: or finding the average height of a list of people?
[2:03 PM] aszs: let's forget about iterators for a second and just consider callback(array)
[2:03 PM] brian_skinner: okay
[2:04 PM] aszs: put aside performance issues if the results are too big
[2:04 PM] aszs: do u think callback(array) make sense?
[2:04 PM] brian_skinner: if we ignore the too-big thing
[2:04 PM] jaxsphere__: onCompletion(array)
[2:04 PM] aszs: yes
[2:04 PM] aszs: jaxasphere: yes
[2:04 PM] brian_skinner: then, personally, i would rather deal with an array than the forEach() thing
[2:05 PM] aszs: would u rather deal with an array than an iterator?
[2:05 PM] brian_skinner: but to be honest, i don't think i can actually do anything more with the array that i couldn't do with the forEach() -- it's just a different syntax for looping through a list and keeping pointers to items i care about
[2:05 PM] jaxsphere__: so what if the results are a dom tree?
[2:06 PM] brian_skinner: yes, rather deal with an array than an iterator
[2:06 PM] jaxsphere__: not a flat arr
[2:06 PM] -->| sjmiles (n=fzappa@c-67-169-54-74.hsd1.ca.comcast.net) has joined #dojo-meeting
[2:07 PM] brian_skinner: hey sjmiles
[2:07 PM] sjmiles: hi brian
[2:07 PM] brian_skinner: jaxsphere__ -- query result may be a graph or a tree, but won't there always be some starting point -- a root node or a list of query result items that are "roots" into the graph
[2:08 PM] aszs: brian: foreach called inside an oncompletion callback would be same
[2:08 PM] brian_skinner: sjmiles: we're doing the dojo.data meeting -- agenda here http://dojo.jot.com/2006-09-26
[2:08 PM] sjmiles: (you guys are kicking butt on dojo.data ... kudos)
[2:08 PM] brian_skinner: sjmiles: thank!
[2:08 PM] aszs: but not if foreach is outside the completion
[2:08 PM] aszs: callback
[2:09 PM] brian_skinner: aszs: what's the difference?
[2:09 PM] aszs: if it is, and the foreach is async you can't get the state out
[2:09 PM] aszs: for example:
[2:11 PM] aszs: var test = false;
[2:11 PM] aszs: result.foreach(function(item) {
[2:11 PM] aszs:   if (item blahblah) test = true;
[2:11 PM] aszs: });
[2:11 PM] aszs: if (test) //!wrong foreach hasn't been called!
[2:12 PM] aszs: oncompletion() {
[2:12 PM] aszs: var test = false;
[2:12 PM] aszs: foreach( function() {if (blah) test = true; }
[2:12 PM] aszs: if (test) //ok
[2:12 PM] aszs: }
[2:12 PM] aszs: do that make sense?
[2:12 PM] brian_skinner: but won't that first example work, if you just have an oncomplete callback that gets called after you're done looping
[2:13 PM] brian_skinner: var finished = false;
[2:13 PM] brian_skinner: oncomplete = function() { finished.true; }
[2:13 PM] brian_skinner: etc.
[2:13 PM] aszs: var test = false;
[2:13 PM] aszs: for each ( { as above)} );
[2:13 PM] aszs: oncompletion() { if (test) blah}
[2:13 PM] aszs: yes
[2:13 PM] aszs: that works
[2:13 PM] aszs: but quite ugly
[2:14 PM] aszs: javascript coders are not hard core engineers
[2:14 PM] brian_skinner: right, it's uglier because it has to deal with the asyc case
[2:14 PM] aszs: oncompletion(array)  is much easier to understand and use
[2:15 PM] brian_skinner: i think it might make sense to have some simpler API for people who don't want to deal with the async case
[2:15 PM] aszs: (i'm most javascript coders aren't)
[2:15 PM] aszs: the ones here are of course ;)
[2:15 PM] brian_skinner: but why not just just findArray()?
[2:15 PM] aszs: is findArray not async?
[2:16 PM] aszs: i'd rather make the async case easier
[2:16 PM] brian_skinner: right, i suggest making findArray not async
[2:16 PM] aszs: oncompletion(array) is easy and async
[2:16 PM] aszs: async is very important IMHO
[2:16 PM] aszs: AJAX u know
[2:17 PM] brian_skinner: oncompletion(array) would require every implementation to always keep an entire array of the whole result list -- right now the API doesn't have the requirement
[2:17 PM] aszs: btw, did u notice i had to rewrite yr test cases to support async?
[2:17 PM] aszs: they have to any way
[2:17 PM] aszs: i argued against
[2:17 PM] aszs: that
[2:17 PM] aszs: calling foreach multiple times creates that requirement
[2:18 PM] brian_skinner: if we add oncompletion(array), then nobody can write an implementation where forEach loops over 1,000,000 items, only loading 100 in memory at a time
[2:18 PM] aszs: i agree
[2:18 PM] brian_skinner: calling foreach multiple times could just load hit the server multiple times
[2:18 PM] aszs: sure...
[2:19 PM] aszs: anyways i agree
[2:19 PM] aszs: making a socratic argument here
[2:19 PM] aszs: next i'm going to argue that iterator is almost as good as array
[2:19 PM] aszs: and that we should use callback(iterator)
[2:20 PM] aszs: for (var item; !iter.atEnd(); item = iter.get())
[2:20 PM] aszs: just like for (var i = 0; i<i.length; i++)
[2:20 PM] brian_skinner: i still don't see how an iterator can do anything that forEach can't
[2:20 PM] aszs: go back to the code example
[2:21 PM] aszs: of course it doesn't; neither does using an array
[2:21 PM] brian_skinner: but you have to compare apples to apples -- if you wait to use the forEach until after your callback has been called, just like you're waiting to use the iterator until after the callback is called
[2:21 PM] jaxsphere__: aszs: +1 onCompletion(iter), if add setPosition() to iter
[2:22 PM] jaxsphere__: and treat iter as an iterface, not a class
[2:22 PM] aszs: yes
[2:22 PM] jaxsphere__: then i can position myself within the results,
[2:23 PM] jaxsphere__: and the impl of the collection is hidden
[2:23 PM] jaxsphere__: so can be complex caching collection impl, etc
[2:23 PM] brian_skinner: but still support the forEach() part of the API?
[2:23 PM] aszs: +1 on jaxsphere's suggestions
[2:23 PM] jaxsphere__: if you use iter, you wont need forEach
[2:24 PM] jaxsphere__: you get map() for free
[2:24 PM] aszs: but map creates an array
[2:25 PM] jaxsphere__: bah
[2:25 PM] brian_skinner: but with the onCompletion(iter), you're saying it's not possible to start processing any results until all the results have been loaded, right?
[2:25 PM] aszs: i'm surprised iterator doesn't have a foreach
[2:25 PM] aszs: yes, i think we should have both
[2:25 PM] aszs: foreach and oncompletion(iter)
[2:25 PM] aszs: that's basically my implementation right now
[2:26 PM] jaxsphere__: i think we need a couple code examples
[2:27 PM] aszs: have u looked at my RemoteStore?
[2:27 PM] jaxsphere__: i mean from client side of the api
[2:27 PM] aszs: i can add more test cases
[2:28 PM] aszs: if there are suggestions on what kinds of examples
[2:28 PM] jaxsphere__: how would this look for 100000 record result set, where i want to start with displaying the the first page of 20 items,
[2:28 PM] brian_skinner: having both seems reasonable on a relatively sophisticated implementation, like the RemoteStore or the IBM XML store -- but for something like the simple CSV store, or a store that just reads data from an HTML <UL> list, then it seems like overkill to require both forEach() and an iterator on every conforming datastore implementation
[2:28 PM] jaxsphere__: next click nextPage and get items 21-40
[2:28 PM] jaxsphere__: then go to page 400
[2:28 PM] jaxsphere__: to retrieve items 400-420
[2:30 PM] jaxsphere__: can we try creating examples of what we want each of these scenarios would look like?
[2:30 PM] aszs: brian: for_each is trivial to implement for a simple store, no?
[2:31 PM] aszs: conversely passing an iterator to callback() is even more trivial
[2:31 PM] aszs: jaxsphere: ok
[2:33 PM] aszs: nextbutton.onclick = function() {???}
[2:34 PM] aszs: if there results are streaming in, forEach(start:,end:) make sense
[2:34 PM] aszs: oops smilely errs
[2:35 PM] aszs: so we can start displaying before completion
[2:35 PM] jaxsphere__: 	var bhsStore = new dojo.data.csv.BigHonkinStore({...});
[2:35 PM] jaxsphere__: var results = bhsStore.find({...query with lots of results});
[2:36 PM] jaxsphere__: (the BHS store impl doesnt retrieve any items at this point, but the results are available remotely)
[2:37 PM] brian_skinner: aszs: for the simple CSV implementation, the datastore class itself was 200 lines of code, including parsing weird CSV corner cases -- the result class was 80 lines of code, nearly 1/3 of the total code, just to deal with looping over an array
[2:37 PM] jaxsphere__: Now, in my init handler in my ui controller, i get the first 20 items
[2:37 PM] brian_skinner: aszs: adding support for both forEach and an iterator would further bloat the result class
[2:39 PM] brian_skinner: sorry jaxsphere__ -- didn't mean to cut you off
[2:40 PM] jaxsphere__: onInit(){
[2:40 PM] -->| ttrenka (n=ttrenka@c-24-118-178-68.hsd1.mn.comcast.net) has joined #dojo-meeting
[2:40 PM] aszs: oncompletion(callback) { callback(new dojo.collections.Iterator(this._arrayOfItems)); }
[2:40 PM] aszs: its one line
[2:40 PM] brian_skinner: hey ttrenka
[2:40 PM] ttrenka: hey guys, sorry I haven't been here
[2:41 PM] ttrenka: sticking my head up for a few minutes, thought I'd pop in and see if you were still going
[2:41 PM] brian_skinner: ttrenka: agenda -- http://dojo.jot.com/2006-09-26
[2:41 PM] brian_skinner: resolutions so far
[2:41 PM] aszs: brian: foreach is where all the code is
[2:41 PM] aszs: not in callback(iterator)
[2:41 PM] brian_skinner: 1. forEach() -- match javascript 1.6 syntax
[2:41 PM] brian_skinner: 4. cancel() cancels everything -- abort XHR, iter, callbacks, etc.
[2:42 PM] jaxsphere__: add for each to iterator... wont need to be on Results
[2:42 PM] ttrenka: brian_skinner: are you asking my opinion on those?
[2:42 PM] ttrenka: jaxsphere__: actually, Iterator has map
[2:42 PM] brian_skinner: now we're talking about how to loop over result lists -- forEach() vs. iterators vs. some way to just get a simple array
[2:42 PM] aszs: but it returns an array
[2:42 PM] ttrenka: which is the same but it returns the resultant array
[2:43 PM] jaxsphere__: y, but aszs pointed out it uses array
[2:43 PM] ttrenka: I can implement forEach if you want
[2:43 PM] aszs: +1 on foreach in Iterator
[2:43 PM] ttrenka: ...the way I did it was to implement map on the Iterator but forEach on the actual collection classes
[2:43 PM] brian_skinner: aszs: one line of code -- point taken -- although it does create the dependency on dojo.collections, which we didn't have before
[2:43 PM] ttrenka: so you can do arrayList.forEach
[2:44 PM] aszs: brian: the problem with Result is all that stuff is to deal with async
[2:44 PM] ttrenka: actually, I'm not sure why you couldn't just use map and ignore the result
[2:45 PM] aszs: maybe if we had a SychronousResult class simple synchrouns store could just use that
[2:45 PM] aszs: ttrenka: we don't want to materalize all the results
[2:45 PM] ttrenka: ok
[2:45 PM] ttrenka: aszs: ok, I know I
[2:46 PM] ttrenka: 'm coming in late but I'm still not following
[2:46 PM] ttrenka: functionally forEach and map are almost the same, it's just that map expects to populate a new array.  But the way they call the callback are pretty much the same
[2:46 PM] brian_skinner: aszs: well, back in an earlier proposal, we did have the dojo.data.Read just deal with the simple Synchronous case, and we had a separate dojo.data.AsyncRead part of the API
[2:46 PM] aszs: we're debating the signature for callback
[2:47 PM] aszs: callback(iterator)
[2:47 PM] aszs: or just callback()
[2:47 PM] brian_skinner: but the consensus was that we should merge the two read APIs, and support the async case as the standard
[2:47 PM] aszs: brian: i agree with that
[2:47 PM] aszs: the SynchrounsResult
[2:48 PM] aszs: would be an internal thing for store implementors to use if there store is not async
[2:48 PM] aszs: basically you've already written it
[2:48 PM] brian_skinner: aszs: i see
[2:49 PM] brian_skinner: yes, i was wondering if we should move dojo.data.csv.Result up out of csv, so that any Synchronous datastore could use it
[2:49 PM] ttrenka: ok, hang on a sec, if you don't mind
[2:49 PM] aszs: i'm looking at yr code, there's nothing csv specific
[2:49 PM] aszs: it just wraps an array
[2:49 PM] brian_skinner: aszs: right, it just wraps and array
[2:49 PM] aszs: ttrenka: ok
[2:49 PM] ttrenka: only because I'm knee deep in feature stuff right now and there's a deadline for tomorrow--should I turn around and implement forEach on the Iterators then?
[2:50 PM] aszs: regardless of our needs here, i'd say yes if you have a map
[2:50 PM] brian_skinner: ttrenka: don't implement until we have some agreement ;-)
[2:50 PM] ttrenka: sigh
[2:50 PM] ttrenka: ok
[2:50 PM] ttrenka: i'll push that off for 0.5 then
[2:51 PM] ttrenka: one thing to note is that using map on an Iterator does not advance the position of the internal cursor
[2:51 PM] ttrenka: just so you know
[2:53 PM] aszs: Array.foreach(iter.a,fn,scope);
[2:53 PM] ttrenka: sorry to interrupt.
[2:53 PM] aszs: that should work with 1.6, right?
[2:53 PM] ttrenka: in theory.  scope is optional
[2:53 PM] ttrenka: note that's only in Moz.
[2:54 PM] brian_skinner: aszs: did you have three args there?
[2:54 PM] ttrenka: no one else supports it yet, and I think it highly unlikely MS will support it anytime soon
[2:54 PM] aszs: you could monkey patch the prototype
[2:54 PM] aszs: ok, sorry to distracted
[2:54 PM] ttrenka: that would screw up anyone who tries to pull for(var i in array)
[2:55 PM] ttrenka: that's why there's an implementation of forEach in dojo.lang, but not directly on an array prototype
[2:55 PM] brian_skinner: should we table this iteration topic for now?  maybe wait on having some examples like what jaxsphere__ was talking about -- how the different proposals look in terms of using them?
[2:55 PM] aszs: oh, so a user could just use dojo.lang.foreach()?
[2:55 PM] ttrenka: aszs: forEach, yes
[2:55 PM] ttrenka: dojo.lang.forEach(array, fn, scope)
[2:55 PM] aszs: if so, i don't care so much
[2:56 PM] ttrenka: if it's a true array or array like
[2:56 PM] ttrenka: collections doesn't fall into that category
[2:56 PM] aszs: oh
[2:56 PM] ttrenka: but most of the collections classes will return you either a true array or a hash if you ask for it
[2:57 PM] ttrenka: depends on the class you're using
[2:57 PM] brian_skinner: ttrenka: going back... "brian_skinner: are you asking my opinion on those?"
[2:57 PM] ttrenka: brian_skinner: yeah?
[2:57 PM] brian_skinner: yes, interested in your opinion
[2:57 PM] ttrenka: ok
[2:57 PM] brian_skinner: especially if you have any objections
[2:57 PM] ttrenka: frankly I was pretty annoyed by Alex's email
[2:57 PM] ttrenka: since he's been participating and has had plenty of opportunities to speak before
[2:58 PM] brian_skinner: i think he may have missed that one meeting
[2:58 PM] brian_skinner: away travelling
[2:58 PM] ttrenka: its the tone more than the request.
[2:58 PM] brian_skinner: yes, the tone was sharp
[2:58 PM] ttrenka: ...so here's the thing.
[2:59 PM] ttrenka: my own opinion is that I think 1. its unlikely MS will implement these extensions, and 2. others, if they follow, will do it slowly
[2:59 PM] ttrenka: in many ways it will probably be the same kind of thing as getters and setters
[2:59 PM] ttrenka: in that it's only Moz and won't get huge adoption.
[2:59 PM] ttrenka: ...so I'm fine with a dual signature forEach.
[2:59 PM] ttrenka: simple case: callback function.
[2:59 PM] ttrenka: more complex: object.
[3:00 PM] brian_skinner: fair enough, but is there any reason not to conform to the Moz spec?
[3:00 PM] ttrenka: we can't
[3:00 PM] ttrenka: and we're not doing an array
[3:00 PM] ttrenka: we're doing a resultset
[3:00 PM] ttrenka: there's a diff
[3:00 PM] brian_skinner: "we can't"?
[3:00 PM] ttrenka: ...I guess what it comes down to for me is that the name of the method should be the most intuitive name we can consider
[3:01 PM] ttrenka: brian: sorry, I mean it's not an array, therefore its not something we can really conform to.
[3:01 PM] aszs: actually foreach is implemented in actionscript 3
[3:01 PM] ttrenka: besides, are you thinking of passing scope to our forEach?
[3:01 PM] ttrenka: that's the key element.
[3:01 PM] ttrenka: also, the Moz spec is a static method, iirc
[3:01 PM] ttrenka: it's not [].forEach
[3:02 PM] ttrenka: it's Array.forEach([], fn)
[3:02 PM] ttrenka: although I could be off on that
[3:02 PM] ttrenka: (looking)
[3:02 PM] aszs: its both i'm pretty sure
[3:02 PM] ttrenka: yeah, ok, seeing that now
[3:03 PM] brian_skinner: it does have
[3:03 PM] brian_skinner: [2, 5, 9].forEach(printElt);
[3:03 PM] brian_skinner: would it be bad to just do:
[3:03 PM] brian_skinner: result.forEach(foo.callback, foo)
[3:03 PM] brian_skinner: or
[3:03 PM] ttrenka: where foo is?
[3:03 PM] brian_skinner: result.forEach(callback)
[3:03 PM] brian_skinner: foo is some object that has a callback method that you want called
[3:04 PM] ttrenka: would foo incorporate other things?
[3:04 PM] ttrenka: i guess I'm asking if that would be similar to the keyword object we've been discussing?
[3:04 PM] brian_skinner: no
[3:04 PM] aszs: forEach(callback, scope, optionalkw)
[3:04 PM] ttrenka: hmmm
[3:04 PM] brian_skinner: if you want keywords, you do this
[3:04 PM] aszs: that's the proposal
[3:04 PM] brian_skinner: result.forEach(foo.callback, foo, {start: 100, end: 199});
[3:04 PM] ttrenka: aszs: I see.
[3:05 PM] ttrenka: brian_skinner: what if someone didn't want to pass the scope object?
[3:05 PM] brian_skinner: then you pass null
[3:05 PM] ttrenka: ok
[3:05 PM] ttrenka: i'm fine with that
[3:05 PM] brian_skinner: slightly ugly, but not that bad
[3:05 PM] brian_skinner: okay, marking as resolved
[3:05 PM] ttrenka: as long as we aren't requiring a shit ton of args :)
[3:06 PM] ttrenka: and the sig remains stable, I'm happy with it
[3:07 PM] brian_skinner: okay
[3:08 PM] brian_skinner: ttrenka: and the other resolution -- cancel() cancels everything -- abort XHR, iter, callbacks, etc.
[3:08 PM] brian_skinner: you okay with that
[3:08 PM] ttrenka: i'm not the best person to ask :)
[3:08 PM] brian_skinner: ?
[3:08 PM] ttrenka: probably if you're going to do that, you'll also need a way of implementing a cancel on individual things as well
[3:09 PM] brian_skinner: individual things?
[3:09 PM] aszs: we talked abou that but decided to punt
[3:09 PM] ttrenka: aszs: ok
[3:09 PM] aszs: i.e. stoping the current foreach
[3:09 PM] ttrenka: brian_skinner: yeah, meaning canceling individual interations
[3:09 PM] ttrenka: iterations
[3:09 PM] brian_skinner: right, punt
[3:09 PM] ttrenka: (bah, can't type today)
[3:09 PM] ttrenka: k
[3:09 PM] brian_skinner: okay
[3:10 PM] ttrenka: then I'm neutral, don't know enough about it to say
[3:10 PM] ttrenka: frankly I don't know enough about most of what you've been proposing.
[3:10 PM] brian_skinner: okay, marking as resolved
[3:10 PM] brian_skinner: do you all want to take on other agenda items?
[3:10 PM] ttrenka: but given the hell I went through when I opened up the iterator discussions to the public, I feel I'm qualified to talk about that :)
[3:11 PM] aszs: its getting late...
[3:11 PM] brian_skinner: yup, i'm a little tired
[3:11 PM] aszs: but one question for jaxsphere
[3:11 PM] brian_skinner: i have a cold -- making me fuzzy
[3:12 PM] ttrenka: sorry to pop in and derail the discussino
[3:12 PM] aszs: jaxasphere: sound like you don't think we need foreach on the result?
[3:13 PM] aszs: well, we made a little progress
[3:14 PM] brian_skinner: aszs, jaxsphere, ttrenka -- do you all want to work on a short write-up of the new looping syntax/semantics that you're proposing?  maybe an example of what it looks like for the UI code?
[3:14 PM] aszs: we agreed on change addcallback to oncompletion, but we don't agree on the callback signature
[3:14 PM] aszs: all i'm proposing is passing an iterator to the callback
[3:14 PM] aszs: nothing else changes
[3:14 PM] brian_skinner: aszs: i think we agreed to change the name of addCallback to something else, but didn't actually pick a name
[3:15 PM] aszs: yes
[3:15 PM] brian_skinner: sadly
[3:15 PM] aszs: ?
[3:16 PM] brian_skinner: and did we agree to not chain callbacks
[3:16 PM] aszs: yes
[3:16 PM] brian_skinner: so then addErrback() should be setErrback() ??
[3:16 PM] aszs: yes
[3:16 PM] brian_skinner: or onerror(), if we want to match oncompletion() ??
[3:17 PM] brian_skinner: or setErrback(), and setCompletionback()
[3:17 PM] brian_skinner: or something?
[3:17 PM] aszs: yes
[3:17 PM] aszs: something
[3:17 PM] brian_skinner: any preferences?
[3:17 PM] brian_skinner: anyone?
[3:17 PM] aszs: hmm
[3:17 PM] ttrenka: sorry
[3:18 PM] ttrenka: i don't have any prefs but I have to run
[3:18 PM] aszs: what the dojo naming convention
[3:18 PM] aszs: for callback?
[3:18 PM] brian_skinner: okay, see you later -- thanks for coming by
[3:18 PM] aszs: ttenka: ok, bye
[3:18 PM] ttrenka: there really isn't any
[3:18 PM] ttrenka: later
[3:18 PM] |<-- ttrenka has left freenode ()
[3:19 PM] brian_skinner: i'm not sure there's a convention
[3:19 PM] aszs: hmm
[3:19 PM] brian_skinner: dojo.io.bind() has "load" and "error" keywords which take callbacks as args
[3:19 PM] aszs: i don't know, setcompletionback sounds strange
[3:19 PM] aszs: setcompletionlistener?
[3:20 PM] sjmiles: fwiw, twisted uses "callback" and "errback" ... that's as close to a convention that I know
[3:20 PM] aszs: handler?
[3:20 PM] brian_skinner: dojo.event.connect() has targetObj and targetFunc as callback keywords
[3:20 PM] aszs: setCompletionFunc()?
[3:21 PM] aszs: io.bind uses handler keyword
[3:21 PM] brian_skinner: setCompletionFunc() -- but, it may not be just a function, right -- may be an object and a method of that object -- which i guess is a function, but i think of that as a method
[3:22 PM] aszs: handle
[3:22 PM] aszs: actually
[3:22 PM] brian_skinner: io.bind uses handle or load or error
[3:22 PM] aszs: yes
[3:22 PM] sjmiles: sorry I'm butting in ... dojo.deferred has an API for this ... are you diverging for a particular reason?
[3:22 PM] aszs: don't ask ;)
[3:23 PM] brian_skinner: sjmiles: butting in is encouraged
[3:23 PM] aszs: we just agreed to diverge
[3:23 PM] aszs: after trying to converge
[3:23 PM] brian_skinner: but yes, we are diverging for a few reasons
[3:23 PM] brian_skinner: well, maybe only a couple reasons
[3:23 PM] sjmiles: ok, good enough
[3:25 PM] aszs: addCallback name is too generic and chaining is hard to implement
[3:25 PM] aszs: and probably not what the user expects
[3:26 PM] brian_skinner: hard to implement would be okay if we were just doing one implementation, but instead we defining an API that we want to make it easy for people to implement, and implement correctly
[3:26 PM] aszs: sjmiles: any suggestion on a name for setting the oncomplete handler?
[3:26 PM] sjmiles: sorry, IMO, it would be addCallback ... but you guys have already ruled it out and I don't want to make you rehash that =P
[3:27 PM] brian_skinner: even "oncomplete" is maybe less descriptive than it could be -- loadComplete vs. loopComplete
[3:28 PM] brian_skinner: setLoadCompleteHander() -- but I'm always a fan of long descriptive names that everybody else hates ;-)
[3:28 PM] sjmiles: setOnLoaded
[3:28 PM] aszs: setOnCompleted?
[3:28 PM] aszs: "load" isn't good
[3:28 PM] brian_skinner: setOnLoaded() and setOnError()
[3:29 PM] brian_skinner: why isn't load good?
[3:29 PM] aszs: the methods find() not load
[3:29 PM] brian_skinner: i see
[3:29 PM] aszs: setOnFindCompleted()?
[3:29 PM] sjmiles: setOnFound (I have minimal information, but if it's find, then it's found =P)
[3:30 PM] aszs: setQueryDone()
[3:30 PM] aszs: setFindDone?
[3:30 PM] aszs: setOnQueryDone?
[3:30 PM] aszs: setOnFindDone?
[3:30 PM] sjmiles: ah, the joys of naming
[3:30 PM] brian_skinner: ;-)
[3:30 PM] sjmiles: it's a tough one
[3:30 PM] brian_skinner: i like setOnFindCompleted()?
[3:31 PM] aszs: ok
[3:31 PM] brian_skinner: okay, i'll put that in as the resolution for now, and we can always change it again when somebody has a better idea
[3:32 PM] aszs: cool
[3:32 PM] aszs: ok, i'm gonna take off now
[3:32 PM] brian_skinner: okay -- thanks for coming
[3:33 PM] brian_skinner: hopefully next week will go faster :-)
[3:33 PM] aszs: thanks for hosting this
[3:33 PM] aszs: yes
[3:33 PM] aszs: but i expect these things to be slow
[3:33 PM] aszs: i've set on standards committees before
[3:33 PM] aszs: they're slower

Attachments (0)

  File By Size Attached Ver.