如何将同步API与异步子类一起使用

时间:2018-05-21 19:55:54

标签: javascript asynchronous promise

我有一个小的npm包实用程序Utilities,我希望在我的两个代码库AppAAppB中使用它。

实用程序将公开一个具有某些功能的类,AppA和AppB的工作是在需要的地方进行子类化。

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);
  }
}

Utilities包以同步方式编写,app A也是如此。然而,AppB需要与validateData内的一些异步方法连接。但是,我的Utilities类不知道消费者有异步API。

我可以轻松更改Utilities和AppB,但不能更改AppA。因此,我需要一种以可在同步和异步环境中工作的方式编写实用程序的方法。

理想情况下,我只是修改AppB并让它等待:

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

但是,这仍然会返回Promise对象而不是实际结果,因为它是异步函数。

另一个缺乏工作的解决方案是在Utilities中的processData内部等待:

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

但是,这会破坏AppA,因为它的实现不是异步,我无法更改AppA。

我有什么选择吗?也许是一种默认设置所有函数await的方法?

这是一个小提琴:https://jsfiddle.net/1ptoczh7/3/

注意AppB结果未定义。我需要能够在不改变AppA的情况下获得两个输出。

1 个答案:

答案 0 :(得分:0)

  

我需要一种以可在同步和异步环境中工作的方式编写实用程序的方法。

编写两个不同的实用程序。无论如何,你几乎肯定会以此结束。将公共代码分解为共享模块(有关如何有效地执行此操作,请查看this answer)。异步功能与同步功能完全不同。

在您的示例中,这很可能如下所示:

function getLength(result) {
  return result.length;
}

class Utilities {
  processData(data) { // returns int
    return getLength(this.validateData(data));
  }
  // abstract validateData(data): Result
  // to be overwritten in subclass
}
class AsyncUtilities {
  processData(data) { // returns Promise<int>
    return this.validateData(data).then(getLength);
  }
  // abstract validateData(data): Promise<Result>
  // to be overwritten in subclass
}