On 3/17/15, Ashley Gullen <ash...@scirra.com> wrote:
> Making toBlob return a promise is definitely in keeping with the rest of
> the web platform, but it's easy to write a wrapper function to promisify
> it. IMO toBlob is better than toDataURL since it is async so the image
> encoding can happen off main thread, reducing jank. I don't know how easy
> it is for existing implementations to change - is it easy to return a
> promise if no callback is provided?
>

Do you want the promise to provide an error handler or is this just
for style consistency?

// current API
canvas.toBlob(callback, type, options);

// Promise with & without error handler
canvas.toBlob(type, options).then(callback, errback);
canvas.toBlob(type, options).then(callback)
canvas.toBlob(type).then(callback);
canvas.toBlobl().then(callback);

You could write a wrapper, but I think it's not as simple as you think it is.

Optional middle argument overloading adds complexity. And the
complexity of adding that complexity is propagated to anyone using
that API. Because then, if they wanted to get a Promise from toBlob,
they would first need to feature test the environment see if
`canvas.toBlob()` with no arguments returns a promise.

Then, after you've feature tested, you'll need to branch to handle the
environments which aren't up to speed with the new promise-returning
canvas.toBlob(). This is going to get into the complexity of handling
added complexity in a dynamic deployment environment, and it will also
entail writing a Promise adapter for the fallbacks to the proposal
will need.

Promise support is spotty and ECMAScript 6 isn't done. So you'll need
a fallback for the getBlob adapter branch that handles the
environments where toBlob doesn't return a promise and the environment
doesn't support Promises.

var toBlobSupportsPromise = function() {
  var x = document.createElement("canvas");
  try {
    x = x.toBlob();
    return''+x=="[object Promise]";
  } catch(ex) {
    return false;
  }
}();

A wrapper (untested):

function getBlob(canvas) {
  if (toBlobSupportsPromise) {
    getBlob = function getBlob(canvas) {
      return canvas.toBlob();
    };
  } else {
    getBlob = function(canvas) {
      return new Promise(function(resolve, reject) {
        canvas.toBlob(function(blob) {
            resolve(blob);
        });
      });
    };
  }
  var ret = getBlob(canvas);
  canvas = null;
  return ret;
}

But then you'll need to add support for Promises, where that isn't
supported. Rewriting a new javascript library sounds like a terrible
idea.

Instead of trying to change toBlob, how about a different-named
function, like `getBlobPromise`? Give browser vendors time and
discourage libraries from trying to write more wrappers, adapters,
polyfills, etc.

Overloading with optional middle arguments creates more problems (like
Dart, Polymer, Angular, etc).

I can definitely understand the lure and attraction of getting sucked
into a promise -- believe me on that!  But when there are too many
things riding on and coupled to it, well, it gets complicated.

Me, I'm a simple guy. I'm fine with callbacks. But I don't mind
exploring these API design ideas.
-- 
Garrett
@xkit
ChordCycles.com
garretts.github.io
personx.tumblr.com

Reply via email to