发射已排序的数组会导致该数组自行取消排序

时间:2019-02-22 14:15:50

标签: arrays angular typescript

我已经找到了解决方法,但是我仍然很想知道是什么原因造成的。我正在为此项目使用Angular 7。

我试图对服务中的对象数组进行排序,然后将经过排序的数组通过主题传递给组件。由于某种原因,组件始终会收到未排序的数组。该阵列是通过Websocket从服务器提供的。

本质上,代码看起来像这样

private sortedData: Data[] = [];
private dataSubject= new BehaviorSubject<Data[]>([]);

//The component is subscribed to this observable
public data$ = this.dataSubject.asObservable();

public getData() { // Called from the component class
        this.apiService('command', this.callback)
    }

private callback = (err: any, data: Object[]): void => {
        if (err) {
           //Error handling code, irrelevant to the problem
        } else {
           this.sortedData = data.sort((a,b) => a.order - b.order);
           this.dataSubject.next(this.sortedData); 
        }
    }

我尝试过的一些东西

  • 通过Object.assing([],data);将数据值分配给临时变量并操纵温度
  • 添加一个setTimeout(()=> this.dataSubject.next(this.sortedData) ,500)
  • 使apiService返回Observable而不是使用回调
  • 编写自己的排序功能
  • 以上所有内容的组合

上述所有方法均无效。当我在开发控制台中使用ng.probe()检查服务中数组的值时,我可以看到该列表确实不是

这是踢脚线。当我将this.dataSubject.next(this.sortedData);注释掉时,该数组突然被排序。

我通过为sortedData添加吸气剂并完全删除BehaviorSubject来使其工作。

我完全不知道是什么原因造成的,但是我想知道。

编辑

Here是问题代码的简化版本。我无法重现我们的问题,但是有了这个,您将可以更清楚地看到结构。该示例与应用程序之间的唯一区别是,我们在ApiService中使用了Socket.io。

就像我上面说的,我们确实解决了这个问题,但我只是想知道是什么原因造成的。

2 个答案:

答案 0 :(得分:0)

FWIW,我今天遇到了这个问题,并试图对其进行调试。在我的情况下,预订主题的组件是一个表行排序器,并通过另一个键对发出的数组进行(重新)排序(因为我想通过引用来对它进行排序)。

我的解决方案是发出已排序数组的副本,因为我在其他地方需要原始已排序数组。

这可能对您或其他人有帮助。仔细查看订户对发出的值的处理方式,以及未排序的数组是否按其他属性排序。

答案 1 :(得分:-1)

尝试使用rxjs方式将这种排序逻辑包含在服务中,那么您就不需要任何辅助主题。

定义getData()方法的位置

this.apiService('command', this.callback).pipe(
  map((data) => {
    const sorted = data.sort((a, b) => a.order - b.order)
    return sorted;
  })
);

然后您可以在组件中直接订阅它,或将其分配给Observable变量以html呈现

ngOnInit(): void {
  this.data$ = this.apiService.getData();
  // then use it in html: <div *ngFor="let item of (data$ | async)">{{item.order}}</div>

  // or subscribe to it in the component
  this.apiService.getData().subscribe((data) => {
    this.data = data;
  })
}