TypeScript中subscribe内this.engines_compare为undefined但外部正常问题
this.engines_compare为undefined,但外部可正常访问 我遇到了一个奇怪的问题:在subscribe的回调函数内部,this.engines_compare显示为undefined,但在subscribe外部却能正常使用这个变量。相关代码如下:
baja(){ this._restService.getEngines(this._globalService.currentFisherMan.nid).subscribe((data : any[]) => { let state = 0; for (let index = 0; index <= data.length; index++) { for (let l = 0; l <= this.engines_compare.length; l++) { if(data[index].nid != this.engines_compare[l].nid){ } } } console.log(this.engines_compare); }); this.sube(); }
嘿,这个问题我太熟悉了!本质上要么是this指向的绑定问题,要么是异步操作的执行顺序导致变量还没初始化,咱们一步步来解决:
一、排查this指向(最常见的原因)
虽然你代码里用了箭头函数(这本来是正确的做法,箭头函数会自动捕获外部上下文的this),但还是有两种保险的方式确保this指向组件实例:
1. 提前保存组件的this引用
有时候在复杂嵌套场景下,箭头函数也可能出现意外(虽然少见),可以提前把组件的this存成一个变量,比如that,然后在回调里用that代替this:
baja(){ const that = this; // 先把组件的this存起来 this._restService.getEngines(this._globalService.currentFisherMan.nid).subscribe((data : any[]) => { let state = 0; for (let index = 0; index < data.length; index++) { // 修复循环越界问题 for (let l = 0; l < that.engines_compare.length; l++) { // 用that访问变量 if(data[index].nid != that.engines_compare[l].nid){ } } } console.log(that.engines_compare); }); this.sube(); }
2. 用bind强制绑定this(针对普通函数回调场景)
如果你之前用的是普通函数作为回调(不是箭头函数),那this会指向订阅对象而不是组件,这时候可以用bind(this)强制绑定:
// 如果你用的是普通函数回调 .subscribe(function(data : any[]) { console.log(this.engines_compare); }.bind(this))
不过你已经用了箭头函数,这个可能不是你的问题,但可以作为备用方案。
二、检查变量的初始化时机
如果上面的方法没用,那大概率是异步执行顺序的问题:当subscribe的回调触发时,this.engines_compare还没被赋值,而你在subscribe外部能访问到,是因为外部代码执行时变量已经初始化了。
举个例子:如果this.engines_compare是从另一个异步请求获取的,那可能getEngines的请求先返回了,这时候回调里自然拿不到值。解决办法是确保getEngines的请求在this.engines_compare初始化之后再发起,或者用RxJS的操作符处理依赖:
// 先获取engines_compare,再请求getEngines的数据 this._restService.getEnginesCompare().pipe( switchMap(enginesCompare => { this.engines_compare = enginesCompare; return this._restService.getEngines(this._globalService.currentFisherMan.nid); }) ).subscribe(data => { // 这里this.engines_compare肯定已经有值了 let state = 0; for (let index = 0; index < data.length; index++) { for (let l = 0; l < this.engines_compare.length; l++) { if(data[index].nid != this.engines_compare[l].nid){ // 你的业务逻辑 } } } console.log(this.engines_compare); });
额外提醒:修复循环越界问题
你的代码里还有个小bug:index <= data.length和l <= this.engines_compare.length会导致数组越界!当index等于数组长度时,data[index]是undefined,访问data[index].nid会直接报错。记得改成index < data.length和l < this.engines_compare.length。
内容的提问来源于stack exchange,提问作者Luis Eduardo

