可堆叠功能

时间:2019-10-29 18:38:30

标签: node.js typescript functional-programming modularity control-flow

我正在寻找一种与库无关的“堆栈”功能的方法。我习惯的范式是“中间件”,其中函数内发生的错误可能会引发错误,并且使用context(或req)全局变量来附加新属性或更改现有属性。这些想法可以在expresstype-graphql之类的库中找到。

我正在寻找链接中间件的不可知论方法,而不依赖于这些类型的库。

这是我拥有的各种功能的示例。

我正在努力以某种简洁的方式来编写函数。全局方法不能补充使用打字稿进行正确键入的功能,而且功能也不十分完善。

更具功能性的方法缺乏这种“可链接性”,在这里我可以简单地拥有一系列如下所示的功能。

// logs the start of middleware
context.utility.log(debug, ids.onLoad),
// fetches user by email submitted
context.potentialUser.fetchByEmail(SignupOnSubmitArgs),
// throws error if the user is found
context.potentialUser.errorContextPropPresent,
// checks if passowrd and reenterPassword match
context.potentialUser.signupPassword(SignupOnSubmitArgs),
// creates the user
context.user.create(SignupOnSubmitArgs, ''),
// thows error if create failed in some way
context.user.errorContextPropAbsent,
// adds user id to session
context.utility.login,
// redirects user to dashboard
context.utility.redirect(Pages2.dashboardManage)

有没有工具/库可以编写清晰,可链接的函数,并以可堆叠的方式将它们粘合在一起?

1 个答案:

答案 0 :(得分:1)

返回this通常是能够链接方法的方法。我为您提供了同时显示同步和异步功能的示例:

class ChainedOperations {
  constructor(private value: number){}

  public add(n: number): this {
    this.value += n;
    return this;
  }

  public subtract(n: number): this {
    this.value -= n;
    return this;
  }

  public async send(): Promise<this> {
    console.log(`Sending ${this.value} somewhere`);
    return this;
  }
}

async function somewhereElse(): Promise<void> {
  const firstChain = await new ChainedOperations(1).add(1).subtract(1).send();
  await firstChain.add(1).subtract(2).send()
}

somewhereElse().catch(e => { throw new Error(e) });

为了更好地处理异步功能,您可以在链接的地方使用管道模式,也可以等待最终结果并将其传递给下一个家伙:

abstract class Pipable {
  public pipe(...functions: Function[]) {
    return (input: any) => functions.reduce((chain, func: any) => chain.then(func.bind(this)), Promise.resolve(input));
  }
}

class AClass extends Pipable {

  constructor(private value: number){
    super();
  }

  public add(n: number): number {
    this.value += n;
    return this.value;
  }

  public subtract(n: number): number {
    this.value -= n;
    return this.value;
  }

  public async send(): Promise<number> {
    console.log(`Sending ${this.value} somewhere`);
    return this.value;
  }
}


async function Something(){
  const myClass = new AClass(2);
  const composition = await myClass.pipe(myClass.add, myClass.subtract, myClass.send)(2);
}

Something();

有些人不喜欢从头开始,而是从最后一个功能开始倒退。如果需要,只需将.reduce替换为.reduceRight。如果您喜欢奇特的名称,那么从末尾开始就称为“合成”,而不是管道。