打字稿无法更新HTML中的视图

时间:2018-12-15 12:42:34

标签: html angular typescript

我一直在开发一个应用程序,该应用程序从MongoDB传递用户事件帖子并以HTML呈现它们:

Event-post.ts

ngOnInit() {

this.postsService.getPosts();
this.postSub = this.postsService.getPostUpDateListener()
.subscribe((posts: Post[]) => {
  this.posts = posts;

Event-post.html

 <mat-expansion-panel *ngFor="let post of posts">
<!-- Display event posts -->

这很好。但是,最近我决定创建一个附加功能,该功能允许用户根据与他们所在位置的接近程度来过滤事件。用户输入邮政编码,然后从下拉菜单中选择距离。数据经过一系列计算;将邮政编码转换为经纬度,计算点与点之间的距离,最后根据所需距离进行过滤。

receivePost($event) {
    this.postFilter = $event;

/****************** Convert Event Posts to LAT LNG **********************************/
this.eventPostcode = [];
console.log('Incoming POSTS: ', this.posts);
for (let i = 0; i < this.posts.length; i++) {
  this.geoCodingService.geocodeAddress(this.posts[i].postcode)
  .subscribe(
    location => {
      this.lat = location.lat;
      this.lng = location.lng;
      const e: EventPostcode = {lat: this.lat, lng: this.lng};
      this.eventPostcode.push(e);
     /* console.log('TEST: ', this.eventPostcode);*/
    }
  );
}

/****************** Convert reference post to LAT LNG **************************/
 this.myPostcode = [];
this.geoCodingService.geocodeAddress(this.postFilter)
.subscribe(
  location => {
    this.lat = location.lat;
    this.lng = location.lng;
    const m: MyPostcode = {lat: this.lat, lng: this.lng};
    this.myPostcode.push(m);
    this.calcDist();
  }
);
}

/******************** Calculate distance between each point **********************/

calcDist() {
const posts = [];

const haversineCalculator = require('haversine-calculator');
for ( let i = 0; i < this.eventPostcode.length; i++) {
const start = {
  latitude: this.myPostcode[0].lat,
  longitude: this.myPostcode[0].lng
};
const end = {
  latitude: this.eventPostcode[i].lat,
  longitude: this.eventPostcode[i].lng
};

/***** Filter according to distance (Options: 15, 25, 50 miles) */
 if (haversineCalculator( start, end, {unit: 'mile'}) < this.distFilter) {
 console.log(haversineCalculator( start, end, {unit: 'mile'}));
   posts.push(this.posts[i]);
 }

 }
 console.log('Filtered posts: ', posts);

 this.posts = posts;
}

当我尝试更新视图中的新列表时出现问题。如果我注释掉this.posts = posts,有效地禁用HTML呈现,并通过console.log('Filtered posts',posts)检查过滤后的数组,一切正常。帖子完全按照我的要求进行过滤。但是,一旦尝试在视图中呈现数据,一切就会崩溃。

尽管控制台中没有显示任何明显的错误,但是当我激活事件处理程序时,该过程的执行速度极慢,大约需要8秒钟才能最终更新视图。

除此问题外,当我检查从数据库传递的帖子(this.posts)进入事件处理程序时,每次按Enter时它们都会减少。因此,如果我从数据库中的6个事件开始并筛选到3个,则下次触发该事件时,只有3个事件可用。

我非常感谢任何人对这个问题所提供的任何指导。 感谢您的宝贵时间。

1 个答案:

答案 0 :(得分:0)

  

除此问题外,当我检查从数据库传递的帖子(this.posts)进入事件处理程序时,每次按Enter时它们都会减少。因此,如果我从数据库中的6个事件开始并筛选到3个,则下次触发该事件时,只有3个事件可用。

致电calcDist()时,您会使用经过过滤的新帖子来更新this.post。调用receivePost()时,只需使用this.post即可,而无需对其进行重置。因此,每次调用calcDist()时,都可能会缩短this.post的长度,而且似乎永远不会将this.post重置为原始长度。这可以解释为什么每次您过滤事件时,事件的数量似乎会永久减少。

我也不确定为什么要将latlng保存到类变量中,因为这些类变量将仅包含最后给定的值。即您正在遍历数组并每次都覆盖this.latthis.lng。由于可观察对象是异步执行的,因此您甚至无法保证它们的回调函数将被调用的顺序。您真的不知道this.latthis.lng的最终值是什么。

最后,对api进行观察的可观察对象是异步函数。您似乎依赖它们来同步执行,因为您在this.calcDist()订阅回调的末尾调用了this.geoCodingService.geocodeAddress(this.postFilter)。但是,据您所知,该回调可能会在任何this.geoCodingService.geocodeAddress(this.posts[i].postcode)回调之前执行。意味着this.eventPosts被调用时,this.calcDist()的长度可以为0(即使有 are 事件发布)。

一种可能的解决方案,将您的可观察变量转换为承诺并使用await以确保执行顺序是您想要的。

示例:

async receivePost($event) {

  this.postFilter = $event;
  // as I mentioned, you need some way of resetting posts to get rid of old filtering
  this.posts = originalPosts;

  /****************** Convert Event Posts to LAT LNG **********************************/
  this.eventPostcode = [];

  const geocodedEventLocations = await Promise.all(
    this.posts.map(post => 
      this.geoCodingService.geocodeAddress(post.postcode).toPromise()
    )
  );

  geocodedEventLocations.forEach(location => {
    this.eventPostcode.push({
      lat: location.lat,
      lng: location.lng,
    })
  });

  /****************** Convert reference post to LAT LNG **************************/
  this.myPostcode = undefined; // not sure why you were setting this to an array before...

  const postFilterLocation =
    await this.geoCodingService.geocodeAddress(this.postFilter).toPromise();

  this.myPostcode = {
    lat: postFilterLocation.lat,
    lng: postFilterLocation.lng,
  };

  this.calcDist();
}


/******************** Calculate distance between each point **********************/

calcDist() {
  const posts = [];

  const haversineCalculator = require('haversine-calculator');

  this.eventPostcode.forEach((eventPostcode, index) => {
    const start = {
      latitude: this.myPostcode.lat,
      longitude: this.myPostcode.lng
    };

    const end = {
      latitude: eventPostcode.lat,
      longitude: eventPostcode.lng
    };

    /***** Filter according to distance (Options: 15, 25, 50 miles) */
    if (haversineCalculator( start, end, {unit: 'mile'}) < this.distFilter) {
      posts.push(this.posts[index]);
    }  
  })

   this.posts = posts;
}

我还没有测试过这个例子,可能还有其他问题,但是希望您能理解。

最后,我认为您进行设置是有原因的

const haversineCalculator = require('haversine-calculator');

calcDist()方法调用内,而不是简单地使用

import * as haversineCalculator from 'haversine-calculator';

位于文件顶部(甚至是const haversineCalculator = require('haversine-calculator');位于文件顶部)。