【问题标题】:Angular: pass a method as parameterAngular:将方法作为参数传递
【发布时间】:2019-02-22 14:28:47
【问题描述】:

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

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 作为参数传递。有什么建议吗?

【问题讨论】:

标签: javascript angular typescript


【解决方案1】:

您的代码中有几个问题。

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

其次,如果您想访问服务上的方法。同样,我们可以通过传入方法名称来执行此操作,并且我们可以约束服务具有传入方法名称的方法,该方法返回ObservableObservable 的结果也可以被限制为与我们将分配给它的字段的类型相同,以使该方法是完全类型安全的。

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,要么在调用时使用箭头函数(再次确保服务方法具有正确的@987654328 @)。不过这很容易出错,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 => {}
        );
    }
}

【讨论】:

    【解决方案2】:

    尝试使用以下代码:

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

    【讨论】:

    • 我认为这与 Angular 版本无关。相反,这取决于他使用的是Http 还是HttpClient。同样在上面的例子中,他最终必须订阅response才能真正访问响应数据,这超出了首先使函数通用的整个目的。
    • @SiddAjmera 看看这个帖子stackoverflow.com/a/39296015/6651984
    • 很抱歉。仍然无法理解您要在这里提出的观点。
    • 为什么不呢?作为响应,您将获得genericFunction 提供的通用响应
    猜你喜欢
    • 2010-11-16
    • 2018-09-09
    • 2012-06-08
    • 2018-11-10
    • 1970-01-01
    • 2013-09-11
    • 2011-04-30
    • 2021-04-30
    相关资源
    最近更新 更多