Skip to content

Optional alternate callback method #13

@SlugFiller

Description

@SlugFiller

The current callback method employed by async uses the first argument as an optional error argument, much like the NodeJS callback pattern. This is suitable for NodeJS, and quite useful as the default, but it is not quite as suitable for targets which don't naturally support variadic function. This can especially be a problem for callbacks which return a large number of proper values, having to pad these for an error call.

To support such targets, I suggest using a two-callback pattern, as is commonly used in jQuery and other targets:

public function doAsync(callback_success : Void->Void, callback_error : Dynamic->Void) : Void;

To prevent backwards compatibility issues, I suggest the following syntax:

class MyClass implements async.Build
{
  @asyncCbErr static function foo(x: Int) : Many<Int, Int>
  {
    var a = 1;
    if (x > 0)
      [[a, x]] = foo(x-1);
    return many(a*x, a+x);
  }
}

This is translated to:

class MyClass
{
  static function foo(x: Int, cb : Int->Int->Void, cberr : Dynamic->Void) : Void
  {
    var a = 1;
    function after() {
      cb(a*x, a+x);
    }
    if (x > 0)
      foo(x-1, function(_a, _x) {
        a = _a;
        x = _x;
        after();
      }, cberr);
    else after();
  }
}

The new meta, and the double-brackets prevent any ambiguity, since those do not form any meaningful interpretation in the current syntax.

An added advantage is that passing cberr forward in calls is less expensive than adding a branch on every callback, and can be inlined by optimizing compilers in some cases.

For full compatibility, this:

@asyncCbErr static function a() : Void
{
  [[]] = a();
  [] = b();
}

@async function b() : Void
{
  [[]] = a();
  [] = b();
}

Should translate to this:

static function a(cb : Void->Void, cberr : Dynamic->Void)
{
  a(function() {
    b(function(err) {
      if (err != null) {
        cberr(err);
        return;
      }
      cb();
    });
  }, cberr);
}

static function b(cb : Dynamic->Void)
{
  a(function(){
    b(function(err) {
      if (err != null) {
        cb(err);
        return;
      }
      cb(null);
    });
  }, function(err) {
    cb(err);  // This can probably be optimized for the case where cb takes no more parameters
  });
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions