Re: [WebIDL] Simplify callbacks

On Wed, Dec 14, 2011 at 4:35 PM, Ian Hickson <ian@hixie.ch> wrote:
> On Wed, 14 Dec 2011, Cameron McCormack wrote:
>>
>> Either we embrace object-with-property for all APIs that take callbacks,
>> giving them meaningful method names, or we decide that all future APIs
>> take only Functions.  Allowing object-with-property for new APIs but
>> using handleEvent for them all seems like a sucky compromise to me.
>
> I think that the sucky situation would be to have lots of places that take
> callbacks, but have to keep looking up what the heck the function is
> called in order to use the object form.
>
> Consider an API that you can use whenever a callback is needed to track
> the number of calls to the callback. If every callback uses a different
> function name, you'd have to tell this API what the context of the
> callback was instead of just being able to use it blindly. Consider what
> it would take to change the implementation of such an API from using
> closures to using an object to store data. Suddenly, every call site would
> need to be updated to provide the callback method name.
>
> Don't think of "handleEvent" as meaning "handle a DOM Event object". Think
> of it as "handle an event", the event being "the callback was invoked".
> There's plenty of precedent for callbacks being called "HandleEvent".

We have at least 3 options here:

1. Accept only Functions (except where webcompatibility requires otherwise)
2. Accept Functions and objects with a handleEvent function
3. Accept Functions and objects with a descriptive function name.

If the callback has the same name everywhere then it adds absolutely
no value over simply accepting only functions. People would end up
having to write code like

x = {
  handleEvent: function(args) {
    if (... detect first callback type based on args ...) {
      doStuff();
    }
    if (... detect second callback type based on args ...) {
      doOtherStuff();
    }
    etc;
  },
  doStuff: function() {...},
  doOtherStuff: function() {...},
  moreProps: "here"
}

registerCallbackFunc(x);
registerOtherCallbackFunc(x);


Compare this to:

x = {
  doStuff: function() {...},
  doOtherStuff: function() {...},
  moreProps: "here"
}

registerCallbackFunc(function() { x.doStuff() });
registerOtherCallbackFunc(function() { x.doOtherStuff() });

The latter is much cleaner and understandable. Not to mention that the
first pattern doesn't work at all if you can't tell the types of
callbacks apart based on what arguments they are given.

So for the sake of not introducing useless features, I would say that
1 is strictly better than 2. That way people can use Function.bind and
direct callbacks directly to where they want.


However I think 3 has value in that it allows you to create a single
object which listens to callbacks from many different APIs.

x = {
  onCallbackFunc: function() {...},
  onOtherCallbackFunc: function() {...},
  moreProps: "here"
};

registerCallbackFunc(x);
registerOtherCallbackFunc(x);


I don't think that having to memorize the callback names will be any
worse having to remember any other names in the DOM. I think the DOM
would be an even worse API if we renamed all functions to "function"
and all the properties to "property".

/ Jonas

Received on Thursday, 15 December 2011 09:32:29 UTC