使用动态函数调用在服务中获取正确的"this"



在我的应用程序中,我有一个我认为很聪明的想法,我将在需要相同参数的 3 个不同函数中重用代码,但使用它访问不同的 API 端点。

我尝试将变量分配给服务中的正确端点函数,然后调用该变量,但显然当通过引用调用函数时,this不再引用服务对象?我不确定,但我得到的错误基本上是服务内部未定义this

我的组件内部的功能:

  submitRefurb() {
    let endpoint = this.refurbService.addRefurb;
    if (this.updating) {
      endpoint = this.refurbService.updateRefurb;
    } else if (this.refurb.id) {
      endpoint = this.refurbService.verifyRefurb;
    }
    this.loading = true;
    endpoint(this.refurb).subscribe( //This is where we have the problem
      (result) => {
        console.log(result);
      },
      (error) => {
        this.loading = false;
      }
    );
  }

翻新服务:

@Injectable()
export class RefurbsService {
  constructor(public httpClient: HttpClient, public sharedService: SharedService) {}
  // `this` is undefined if called like it was above
  addRefurb(refurbData, context = [this.sharedService.sectionSelected]) {
    const body = { refurb: refurbData, context};
    return this.httpClient.post(window.location.protocol + '//' + window.location.hostname  + '/refurbs/add', body);
  }
  verifyRefurb(refurbData, context = [this.sharedService.sectionSelected]) {
    const body = { refurb: refurbData, context};
    return this.httpClient.post(window.location.protocol + '//' + window.location.hostname  + '/refurbs/verify', body);
  }
  updateRefurb(refurbData, context = [this.sharedService.sectionSelected]) {
    const body = { refurb: refurbData, context};
    return this.httpClient.post(window.location.protocol + '//' + window.location.hostname  + '/refurbs/update', body);
  }
}

现在,我终于通过简单地将 endpoint 变量赋值为字符串来让它工作,而不是直接将其分配给函数,如下所示:

let endpoint = 'addRefurb'; ... this.refurbService[endpoint](this.refurb)

但我仍然不完全明白出了什么问题,谁能解释一下有什么区别?有没有比我最终的方式更好的处理方法?

你可以使用bind方法:

 submitRefurb() {
    let endpoint = this.refurbService.addRefurb.bind(this.refurbService);
    if (this.updating) {
      endpoint = this.refurbService.updateRefurb.bind(this.refurbService);
    } else if (this.refurb.id) {
      endpoint = this.refurbService.verifyRefurb.bind(this.refurbService);
    }
    this.loading = true;
    endpoint(this.refurb).subscribe( //This is where we have the problem
      (result) => {
        console.log(result);
      },
      (error) => {
        this.loading = false;
      }
    );
  }

使用箭头函数:

let endpoint = (refurbData) => this.refurbService.addRefurb(refurbData);

或者只是存储可观察量而不是端点:

let obs = this.refurbService.addRefurb(this.refurb);
...
obs.subscribe(...)