【问题标题】:ctx. is undefined in Angularctx。在 Angular 中未定义
【发布时间】:2020-10-06 16:17:26
【问题描述】:

我正在开发来自 OpenWeatherMap API 的天气应用程序,由于请求太多,我已经两次阻止了我的服务。我检查了我的代码很多次,我找不到一个会导致服务器循环需求的地方,我检查了控制台,它给出了以下错误:ERROR TypeError: ctx.amindiDGES is undefined .

我在 main.component.html 的几行中收到此错误:

MainComponent_Template main.component.html:8
getLocation main.component.ts:39
ngOnInit main.component.ts:27

这就是我的服务的样子 today.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';

import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class TodayService {
  url = 'http://api.openweathermap.org/data/2.5/weather';
  apiKey = '***********************';

  constructor(private http: HttpClient) { }

daitriecoordinatebi(lat, lon) {
  let params = new HttpParams()
    .set('lat', lat)
    .set('lon', lon)
    .set('units', 'metric')
    .set('appid', this.apiKey)

  return this.http.get(this.url, { params });

这是我的 ma​​in.component.ts

import { Component, OnInit } from '@angular/core';
import { TodayService } from './today.service';


@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.scss']
})

export class MainComponent implements OnInit {
  lat;
  lon;
  amindiDGES;
  kvirisdgeToday;
  ikonkaToday;

  
  title = 'Day1';
  today = new Date();

  constructor(private todayService: TodayService) { }

  ngOnInit(): void {

    // lokacia
    this.getLocation();

    // zusti saati
  

    this.today = new Date();
    

  }

  getLocation() {
    if ("geolocation" in navigator) {
      navigator.geolocation.watchPosition((success) => {
        this.lat = success.coords.latitude;
        this.lon = success.coords.longitude;

        this.todayService.daitriecoordinatebi(this.lat, this.lon).subscribe(data => {
          this.amindiDGES = data;
        })
      })
    }
  }
  
}

这是我的 ma​​in.component.html

的一部分
<table>
  <tbody>
    <tr>
      <td><i class="fas fa-wind"></i></td>
      <td>&nbsp;&nbsp;Wind - {{amindiDGES.wind.speed}}</td>
    </tr>
    <tr>
      <td><i class="far fa-eye"></i></td>
      <td>&nbsp;&nbsp;Visibility - {{amindiDGES.visibility}}</td>
    </tr>
    <tr>
      <td><i class="fas fa-tachometer-alt"></i></td>
      <td>&nbsp;&nbsp;Preassure - {{amindiDGES.main.pressure}}</td>
    </tr>
    <tr>
      <td><i class="fas fa-tint"></i></td>
      <td>&nbsp;&nbsp;Humidity - {{amindiDGES.main.humidity}}</td>
    </tr>
  </tbody>
</table>

所有这一切的有趣之处在于,我从服务器获取数据并且确实看到了结果,但不知何故,由于需求过多,应用程序在使用几次后被阻止,允许的数量是每分钟 60 次,而我的应用程序每分钟需要 800 多个请求,除此之外,控制台中会出现一个持续错误:ERROR TypeError: ctx.amindiDGES is undefined

我的猜测是,应用程序可能会以某种方式尝试在通过服务器获取数据之前显示数据,它会在控制台中给出错误,之后,它会一遍又一遍地发出多个请求,直到 API 被阻塞。

我想知道您在获取数据时是否有这样的问题

【问题讨论】:

  • 另外,请分享daitriecoordinatebi 方法的调用位置。由于数据以异步方式到达,因此您应该在表中添加一些条件渲染,例如 &lt;table *ngIf="amindiDGES"&gt;,它将处理 ctx.amindiDGES is undefined 错误。
  • 我已经包含了代码,在 main.component.ts 中调用了 daitriecoordinatebi。我明白了,所以为了摆脱控制台错误,您需要使用 if 调节,但它隐藏了问题而不是修复它,对吧?或者除非您使用 if 条件,否则通常会使用异步获取控制台错误?
  • 您应该将Observableasync 管道一起使用或与*ngIf 同步

标签: angular typescript httpclient


【解决方案1】:

好吧,下面的函数有一些严重的问题:

 getLocation() {
    if ("geolocation" in navigator) {
      navigator.geolocation.watchPosition((success) => {
        this.lat = success.coords.latitude;
        this.lon = success.coords.longitude;

        this.todayService.daitriecoordinatebi(this.lat, this.lon).subscribe(data => {
          this.amindiDGES = data;
        })
      })
    }
  }

如文件所述:

Geolocation 方法 watchPosition() 方法用于注册一个处理函数,该处理函数将在每次设备位置发生变化时自动调用。

因此,每次位置更改时,您的代码都会订阅 daitriecoordinatebi observable。因此,如果位置更改 3 次,您将拥有 3 个订阅。所以你会调用 API 3 次...

你有很多选择来解决这个问题。

  1. 使用toPromise,然后等待结果
async  (success) => {
    this.amindiDGES = await 
          this.todayService.daitriecoordinatebi(this.lat, this.lon).toPromise();
// or you can use
     await lastValueFrom(this.todayService.daitriecoordinatebi(this.lat, this.lon))
// since toPromise will be deprecated
})
  1. 在管道中使用first 运算符使订阅自动销毁
 this.todayService.daitriecoordinatebi(this.lat, this.lon).pipe(first()).subscribe...
 // or you can use take(1)
  1. 您可以使用SubjectmergeMap 运算符使其更优雅
positionChanged = new Subject();
  getLocation() {
    if ("geolocation" in navigator) {
      navigator.geolocation.watchPosition((success) => {
        this.lat = success.coords.latitude;
        this.lon = success.coords.longitude;
        this.positionChanged.next();        
      })
    }
    this.positionChanged.pipe(
       mergeMap(()=>this.todayService.daitriecoordinatebi(this.lat, this.lon)))
        .subscribe(data => {
          this.amindiDGES = data;
        })
  }

【讨论】:

  • 我想尝试第三种方法,它给出了以下错误:“错误 TS2339 (TS) Property 'subscribe' does not exist on type 'OperatorFunction
  • @SoulFly 它有一个错字,它仍然可能有。您可以在pipe 的右括号后订阅。
猜你喜欢
  • 2021-06-09
  • 1970-01-01
  • 2022-07-20
  • 1970-01-01
  • 2016-01-14
  • 1970-01-01
  • 2019-02-11
  • 1970-01-01
  • 2019-01-05
相关资源
最近更新 更多