最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular: pass a method as parameter - Stack Overflow

programmeradmin0浏览0评论

I have these two methods which are almost similar:

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

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

I want to write a generic function, like this:

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

And consequently I want to get something like this working:

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

Actually, I cannot find how to pass methodOne and methodTwo as params. Any sugestions?

I have these two methods which are almost similar:

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

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

I want to write a generic function, like this:

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

And consequently I want to get something like this working:

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

Actually, I cannot find how to pass methodOne and methodTwo as params. Any sugestions?

Share Improve this question edited Sep 18, 2018 at 14:13 David Walschots 12.7k5 gold badges38 silver badges59 bronze badges asked Sep 18, 2018 at 14:10 firasKoubaafirasKoubaa 6,87729 gold badges87 silver badges163 bronze badges 2
  • Is this what you are looking for ? stackoverflow./questions/14638990/… – Titian Cernicova-Dragomir Commented Sep 18, 2018 at 14:12
  • Are you sure you're not falling into the trap of trying to return a value from an async method? – Jamiec Commented Sep 18, 2018 at 14:18
Add a ment  | 

2 Answers 2

Reset to default 1

There are several issues in your code.

Firstly, you want to modify the field you pass in as a parameter (as suggested by result = res. You can't pass in a reference to a field, but you can pass in the field name, and use indexing to change the field. keyof T will allow you to pass in the field in a type safe way.

Secondly if you want to access a method on a service. Again we can do this passing in the method name, and we can constrain the service to have a method with the passed in method name, that returns an Observable. The result of the Observable can also be constrained to be of the same type of the field we are going to assign it to in order for the method to be fully type safe.

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

Note We could have also passed in the function as a function not just as a name, but directly a typed function. The disadvantage of this is that we either have to use bind to ensure the service method will still have the correct this when it's called, or use an arrow function when calling (again to ensure the service method has the correct this). This is error prone though, bind results in an untyped function, so we can't check patibility to the field, and someone might pass service.method directly and no error would be reported until runtime:

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 inpatible 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 => {}
        );
    }
}

try by using the following code:

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

Modify you Generic Function by just receiving a variable.

//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;
        }));
      }
发布评论

评论列表(0)

  1. 暂无评论