Re: File API Feedback

On Sat, Jul 25, 2009 at 10:18 PM, Jonas Sicking<> wrote:
> On Thu, Jul 23, 2009 at 12:37 AM, Garrett Smith<> wrote:
>> On Wed, Jul 8, 2009 at 5:05 PM, Jonas Sicking<> wrote:
>>> On Wed, Jul 8, 2009 at 2:26 PM, Garrett Smith<> wrote:
>>>> On Mon, Jul 6, 2009 at 1:38 PM, Jonas Sicking<> wrote:
>>>>> On Wed, Jul 1, 2009 at 9:01 PM, Garrett Smith<> wrote:
>>>>>> On Tue, Jun 30, 2009 at 7:36 PM, Jonas Sicking<> wrote:
>>>>>>> On Tue, Jun 30, 2009 at 6:13 PM, Garrett Smith<> wrote:
>>>>>>>> On Tue, Jun 30, 2009 at 4:29 PM, Jonas Sicking<> wrote:
>>>>>>>>> On Tue, Jun 30, 2009 at 4:22 PM, Garrett Smith<> wrote:
>>>>>>>>>>> With that in mind, do you still think it makes sense to have progress
>>>>>>>>>>> events and all the other events you are proposing?
>>>>>>>>>> I've reread my message. The arguments and reasoning given for Events
>>>>>>>>>> seem clear and concise. The argument for Progress Events was
>>>>>>>>>> illustrated with an example and a comparison. What was confusing?
>>>>>>>>> What is the use case for the API you are proposing?
>>>>>>>> The program wants to attach more than one "success" callback at places
>>>>>>>> in the code. The program wants to attach a "timeout" callback, to
>>>>>>>> handle cases where the read operation is too slow.
>>>>>>> But *why* would someone want to attach more than one success callback?
>>>>>> Why would someone want to attach more than one "click" handler to
>>>>>> document? It doesn't really matter why, but it is not hard to imagine
>>>>>> situations.
>>>>>> For example, a notification for all success reads of files to notify
>>>>>> the user of "done", but then specific notifications about the current
>>>>>> file read. Not hard to imagine, but, AISB, it is not necessary to
>>>>>> consider all possible contexts. You have snipped and ignored that and
>>>>>> all other questions. Please don't do that.
>>>>>> AISB, "An asynchronous file read is like an asynchronous XHR, in a
>>>>>> way." It can be desirable to want to have more than one callback for
>>>>>> XHR.
>>>>> I don't know that I've ever seen someone attach more than one
>>>>> eventhandler to an XHR request. In fact, I'm not even sure that IE
>>>>> supports more than one. For the longest time firefox didn't, and I
>>>>> don't think I ever saw a request for attaching more than one.
>>>> Multiple callbacks for XHR are facilitated by custom events. That was
>>>> explained in the "<ajax library aside>" that I wrote.
>>> Sorry, I did not understand how the ajax library aside related to the
>>> original discussion. Reading it again I still don't understand the use
>>> case. I see that you are complaining about the API that the YUI
>>> library has, but I still don't see an explanation of a use case where
>>> you are reading data from a source and wish to have multiple unrelated
>>> listeners notified when that data is read. The way I am reading it you
>>> are saying that you have had this need in the past and that the YUI
>>> library didn't provide that functionality and thus was hard to work
>>> with. Can you explain the situation you were in when you had this
>>> need?
>> OK.
>> <simplification>
>> Two selects on search pane. First select triggers XHR. Regarding that:
>> Busy indicator:
>>  - listens for call being placed and shows UI busy indicator.
>>  - listens to "complete" and hides UI indicator.
>> StubManager listens to success from first.
>> </simplification>
>> The YUI connection manager, in all its gory, did not allow for such
>> clean/sane design. Sadly, the implementation above became a mere
>> fantasy. Using YUI was somewhat of a constraint (an unqualified
>> individual making technical decisions). Thus, callbacks became
>> coupled, called from asyncRequest's "callback" parameter (object)
>> which has "success" and "failure" properties. In that regard YUI
>> ConnectionManager has a leg-up on the FileUpload design because the
>> "callback" object is extensible. That is, "callback" can be given more
>> properties without changing the method signature to "asyncRequest".
>> FileUpload is less extensible. Adding configurable behavior would
>> either require get* methods to accept yet another parameter variable
>> or the addition of new properties on File.
>> file.getDataAtRange(4711, 5735, showFrameHandler, genericError);
>> Could be refactored to:-
>> file.getDataAtRange(4711, 5735, callbacksObject);
>> But that has problems as well.
>> So we're back to DOM Events.
> So the use case you are bringing up is as follows:
> A UI, that uses two <select>s makes a call to read external data.
> While that data is loading it wants to show some UI indicator showing
> that it's loading external data. Once the data has been read it then
> wants to:
> A) Remove that indicator
> *and*
> B) Process the read data (possibly populating the second select?)
> In your example you mention using XHR to read this external data, but
> presumably one might also desire to read data from a File object and
> thus the use case should work then too.
> Do I understand your use case correctly?

Not completely. The way you've worded it also sounds strange to me. I
don't think of it as "the UI wants to remove the indicator". It might
be better to describe only what could be seen by the user, e.g. "the
progress indicator goes away" because it is more neutral.

Let me try again using that approach:
  1) User selects an option from SELECT 1.
  2) SELECT 2 is updated from (data from server)
  3) Other Form controls (may) change, preserving some data (no server
req), though now that I think back, I think this was a result of the
second SELECT changing.

Step 3 was what I had said as "StubManager listens to success from
first.", but now that I think about it, it worked differently. IIRC,
StubManager wanted to listen to the second SELECT changing, which
sometimes happened from script (that does not trigger a change event),
but could also be the result of a user event. A custom event for
(re)broadcasting sounds like a good idea, but I honestly can't
remember what I did.

>> You sound as if you have never been in a position where two objects
>> wanted to get an event notification. Procedural style of coding, e.g.
>> when A happens, do B, then do C. As opposed to, B listens to A, C
>> listens to A.
> I most certainly agree that in some cases when callbacks are used, it
> is appropriate to use the full event notification system provided by
> DOM events.
> I don't however think that *all* callbacks need the full power of the
> event notification system provided by DOM events. A example is the
> TreeWalker[1] interface which uses a callback but does not use DOM
> events.

TreeWalker is a synchronous iterator. Do you think this TreeWalker is
a relevant comparison to file reading/File API? It seems totally
different, to me. Yeah, it has a callback, but so do Array Extras.

I looking at APIs is a great idea. <hot button>By recognizing API
flaws, they can be avoided.</hot button>

window.setTimeout and setInterval take a callback function, too. There
is no native alternative, so no other choice; no Timer API. It IoC
Animation Manager is somewhat hard to get right.

> [1]
>>>>> Similarly, any API for file access that I have ever seen has only used
>>>>> a single callback. And file system APIs have existed for many many
>>>>> years.
>>>>> UI handling is a lot different from file handling so I don't think the
>>>>> analogy with the "click" event is that strong. The only similarity is
>>>>> the use of a callback.
>>>> The user interacts with the file upload mechanism inside the browser. See?
>>> The user does not interact with the file read API in question here.
>>> The callbacks passed to getAsText/getAsDataURL are called in response
>>> to those calls, not in response to any user interaction.
>>>>> So again, can you give an example of where you'd like two listeners
>>>>> notified with data read from the file?
>>>> What was wrong with the first time I posted it?
>>>> Scroll back up and read:
>>>> | For example, a notification for all success reads of files to notify...
>>>> Read the entire paragraph. Think, write, revise, etc.
>>> I did simply not understand your use case before. I still do not as
>>> described above.
>> Explained here:
> So the use case here is to load external data. While the data is
> loading UI is shown to indicate this to the user. Once the load ends,
> successfully or not, the UI is hidden.
> Is this correct?


[snip description of SELECT with two success and one complete event]

>> The Requirements section of the draft briefly describes some very
>> sophisticated applications:
>> Messaging and events would be indispensable there.
>> | #1) Example: A lyrics viewer. User wants to read song
>> | lyrics from songs in his plist file.  User browses for
>> | plist file.  File is opened, read, parsed, and presented
>> | to the user as a sortable, actionable list within a web
>> | application.  User can select songs to fetch lyrics.  User
>> | uses the "browse for file" dialog.
>> When the file reader starts, a message is displayed, e.g. the table
>> caption displays "loading: " +
>> When the file reader completes, the message changes.
>> The Results Table listens for success on the file read, as it receives
>> data, display the results of the songs found in the plist file.
>> Concurrently, a Lyrics Finder makes XHR to get lyrics data from the
>> plist file (which probably has more songs than can be be displayed on
>> the page).
>> The Results Table concurrently listens for success/progress
>> notifications from the remote call (XHR) to update the UI, displaying
>> indication of lyrics for a song being loaded (the "lyrics present"
>> indicator).
> This sounds similar to the first to use cases in that data is loaded,
> and while the data is loaded UI is displayed to indicate this to the
> user. Once the load ends (successfully or not) the UI should be hidden
> and data processed. The biggest difference I see in this use case is a
> request for progress events.
> Is this correct?

Yes, progress events are just as relevant for FileUpload as they are for XHR.

Given no "complete" event, but "success" and "failure" events, it
would be possible to add a removeMessage callback for "success" and
"failure" events. Doing that would have the same effect, but would be
repetitive in the code. The "complete" event solves that problem, and
that is the reason I proposed it and pushed for having it added to the
Progress Events API.

>> The Calendar application might likely be more complicated. Complexity
>> is best addressed by creating objects that have isolated
>> responsibility and that listen for messages of other components,
>> including read events from the file reader.
> I don't understand this. What is "The Calendar application"?

It's under "Requirements and Use Cases"

>> [snip discussion about timeout]
>> [snip Reader proposal explanation]
>>>> That proposal may have some problems. The role of a File originally
>>>> included behavior to read itself. I changed that to give the file a
>>>> "reader" property. From a role perspective, that's still a bit off.
>>>> Why should a file "have" a reader? Why cannot a Reader exist on its
>>>> own? That way, it can be passed a File to read, and some other
>>>> arguments.
>>>> Example:
>>>> file );
>>>> and for ranges:-
>>>> file[, start, end);
>>>> Your question:-
>>>> "How would you do that using the API you are proposing?"
>>>> Use an event handler on the Reader. For example:-
>>>> if(typeof FileReader != "undefined" && "BINARY" in FileReader) {
>>>>  reader = FileReader.create( FileReader.BINARY );
>>>>  if(reader != null) { // Reader was created.
>>>>    reader.addEventListener("success", func, false);
>>>>, i, j);
>>>>  }
>>>> }
>>>> Wrinkly, maybe but the gist.
>>> I understand. I would say that I think the API in the current proposal
>>> is better due to its simplicity.
>> Simplicity is a good reason for using events.
>> Having a separate event interface keeps the File interface simpler and
>> allows the individual callbacks to be simpler.
>> By not using events, everything gets more complicated.
> I'm still trying to understand your use cases. Let me know if the I
> understood your above ones correctly? Once we have the use cases
> collected it will be easier to evaluate pros and cons with the various
> technical solutions.

Take a look at the "Requirements and Use Cases" section of FIleUpload:

 * A lyrics viewer
 * A Calendar App
 * A Spreadsheet App
 * A Video/Photo Upload App

These use cases (very) briefly mention what seem to be complex UI
applications. There's not really detailed use-cases.

Should the current requirements be more elaborate?

We can go as far as writing out an implementation, replete with test
spec. Since no mechanism for reading a file exists (that's what we're
designing), we can stub the file reading mechanism with an adapter.
That adapter can return a string of the file contents, or other
formats, if desired. That mock object uses an async mechanism, such as
XHR, as a substitute. In doing this, it might reveal other issues. For
example, it might be realized that a string value is fine for smallish
1-10kb files, but too CPU-intensive for 10mb files (browser crash).

Doing that would require a good amount of time. First thing would be
deciding on what to do, then next planning some real use cases that
could be tested. We could even make some activity diagrams for the
tricky parts.

Can we derive general principles about how asynchronous mechanisms
provide notifications? Can we apply what is known about communication
between objects and how this is facilitated by DOM Events? Can we draw
parallels from and make inferences regarding XHR? Can we learn a
lesson from the consequence of YUI connection manager's design
decision (which I call a mistake)? Can we see patterns of how use
cases for FileUpload relate to XHR and usage patterns for XHR?

All of the above will be easier than fleshing out an an application.

Developing the application would be the ultimate. If you're local, we
can meet and work on it together. It would take time and though it
would be rewarding, but would not pay. The first thing would be
deciding on what to make and basic requirements. That could be done on
this list.

>> [snip about snips]


> / Jonas



Received on Saturday, 1 August 2009 05:51:55 UTC