角度:将方法作为参数传递

时间:2018-09-18 14:10:35

标签: javascript angular typescript

我有两种几乎相似的方法:

private firstFunction () {
    this.serviceOne.methodOne().subscribe(
      res => {
        return  resultOne = res;
      },
      err => {}
    );
  }

private secondFunction () {
    this.serviceTwo.methodTwo().subscribe(
      res => {
        return  resultTwo = res;
      },
      err => {}
    );
  }

我想编写一个通用函数,如下所示:

genericFunction (service ,method , result  ) {
        service.method().subscribe(
          res => {
            return  result = res;
          },
          err => {}
        );
      }

因此,我想获得类似的效果:

genericFunction (serviceOne , methodOne , resultOne );
genericFunction (serviceTwo , methodTwo , resultTwo );

实际上,我找不到如何将methodOnemethodTwo传递为参数。有任何建议吗?

2 个答案:

答案 0 :(得分:1)

您的代码中有几个问题。

首先,您要修改作为参数传递的字段(如result = res的建议。您不能传递对字段的引用,但可以传递字段名称并使用索引以更改字段。keyof T将允许您以安全的方式传递字段。

第二,如果要访问服务上的方法。再次,我们可以通过传递方法名称来执行此操作,并且可以限制服务以使其具有传入的方法名称的方法,该方法返回Observable。也可以将Observable的结果约束为与我们要为其分配的字段类型相同的字段,以使该方法具有完全类型安全性。

declare class Service1 {
    method1() : Observable<number>
}
declare class Service2 {
    method2() : Observable<string>
}
class MyClass {
    resultOne!: number;
    resultTwo!: string;

    constructor() {
        this.genericFunction(new Service1(), "method1", "resultOne");
        this.genericFunction(new Service2(), "method2", "resultTwo");
        this.genericFunction(new Service1(), "method1", "resultTwo"); // error resultTwo is a string, the method return Observable<number>
        this.genericFunction(new Service2(), "method", "resultTwo"); // error method does not exit on Service2
        this.genericFunction(new Service2(), "method2", "resultTwo2"); // error field does not exist on type 
    }

    genericFunction<MethodKey extends string,  ResultKey  extends keyof MyClass>(service:Record<MethodKey, ()=> Observable<MyClass[ResultKey]>>, method:MethodKey, result: ResultKey){
        service[method]().subscribe(
            res => this[result] = res,
            err => {}
        );
    }
}

注意我们也可以将函数作为函数传递,而不仅是作为名称传递,还应作为类型函数传递。这样做的缺点是我们要么必须使用bind来确保服务方法在调用时仍具有正确的this,要么在调用时使用箭头函数(再次确保服务方法具有正确的this)。不过,这容易出错,bind会导致未类型化的函数,因此我们无法检查对该字段的兼容性,并且有人可能会直接传递service.method,直到运行时才会报告错误:

class MyClass {
    resultOne!: number;
    resultTwo!: string;

    constructor() {
        var service1 = new Service1()
        var service2 = new Service2()
        this.genericFunction(()=> service1.method1(), "resultOne");
        this.genericFunction(()=> service2.method2(), "resultTwo");

        this.genericFunction(service2.method2, "resultTwo"); // no error, depending on the implementation of method2 it might or might not work
        this.genericFunction(service2.method2.bind(service2), "resultOne"); // no error, the service call will work, but we store it in an incompatible variable
        this.genericFunction(()=> service1.method1(), "resultTwo");// error resultTwo is a string, the method return Observable<number>
        this.genericFunction(()=> service2.method2(), "resultTwo2");// // error field does not exist on type 
    }

    genericFunction<MethodKey extends string,  ResultKey  extends keyof MyClass>(method:()=> Observable<MyClass[ResultKey]>, result: ResultKey){
        method().subscribe(
            res => this[result] = res,
            err => {}
        );
    }
}

答案 1 :(得分:0)

尝试使用以下代码:

private firstFunction () {
    let response= genericFunction(this.serviceOne.methodOne())      
}
private secondFunction () {
   let response = genericFunction(this.serviceTwo.methodTwo())    
}

仅通过接收变量即可修改通用函数。

//if it is angular 4 or less
genericFunction (method: Observable) {
        return method.map(res => {
           return res.json();
        });
      }
 //if it is angular 5 or 6
 genericFunction (method: Observable) {
        return method.pipe(            
           map(res => {
           return res;
        }));
      }