Home » Javascript » How to use a synchronous API with an async subclass

How to use a synchronous API with an async subclass

Posted by: admin August 19, 2018 Leave a comment

Questions:

I have a small npm package of utilities Utilities that I want to use across two of my codebases, AppA and AppB.

Utilities will expose a class with some functions, and it is AppA and AppB’s job to subclass where needed.

class Utilities {

  processData(data, callback)  {
    var result = this.validateData(data);
    // This will fail for AppB, because validateData returns a promise.
    var length = result.length;
    callback(length);
  }

  validateData(data) {
    // Must be subclassed
  }

}

AppA:

class AppA extends Utilities {
  validateData(data) {
    return [1, 2, 3];
  }
}

AppB:

class AppB extends Utilities {
  validateData(data) {
    // returns a Promise
    return AsyncMethods.checkData(data);
  }
}

The Utilities package is written in a synchronous manner, as is app A. AppB however requires interfacing with some async methods inside of validateData. My Utilities class however does not know that the consumer has an async API.

I can change both Utilities and AppB with ease, but not AppA. So I need a way to write Utilities in a way that can work in both sync and async environments.

Ideally, I’d just modify AppB and make it wait:

class AppB {
  async validateData(data) {
    var result = await AsyncMethods.checkData(data);
    return result;
  }
}

However, this still returns a Promise object and not the actual result, because it’s an async function.

Another solution that falls just short of working is waiting inside processData in Utilities:

  async processData(data, callback)  {
    var result = await this.validateData(data);
    var length = result.length;
    callback(length);
  }

However, this breaks AppA, as its implementation is not async, and I cannot change AppA.

Do I have any options here? Perhaps a way to make all functions await by default?

Here’s a fiddle: https://jsfiddle.net/1ptoczh7/3/

Notice for AppB the result is undefined. I need to be able to get both outputs without changing AppA.

Answers: