当我 Observable.interval 时如何允许函数 sortbydate()

How to allow a function sortbydate() when I'm Observable.interval

我有这个JSON:

{
    "StatusCode": 0,
    "StatusMessage": "OK",
    "StatusDescription": [
        {
            "id": "1",
            "datetime_device": "2018-05-11 12:05:00",
            "client_name": "Client1"
        },
        {
            "id": "2",
            "datetime_device": "2018-05-11 12:05:00",
            "client_name": "Client1"
        },
        {
            "id": "3",
            "datetime_device": "2018-04-11 12:05:00",
            "client_name": "Client1"
        },
        {
            "id": "4",
            "datetime_device": "2018-01-11 12:05:00",
            "client_name": "Client1"
        },
        {
            "id": "5",
            "datetime_device": "2018-02-11 12:05:00",
            "client_name": "Client2"
        },
        {
            "id": "6",
            "datetime_device": "2018-01-05 12:05:00",
            "client_name": "Client2"
        },
        {
            "id": "7",
            "datetime_device": "2018-05-09 12:05:00",
            "client_name": "Client1"
        },
        {
            "id": "8",
            "datetime_device": "2018-05-01 12:05:00",
            "client_name": "Client1"
        },
        {
            "id": "9",
            "datetime_device": "2018-01-01 12:01:00",
            "client_name": "Client1"
        }
    ]
}

我创建了一个按日期排序的函数 JSON。

  private getTime(date?: Date) {
    return date != null ? date.getTime() : 0;
  }
  public sortbydate(): any[] {
    return this.notification0.sort((a, b) => {
      return this.getTime(new Date(a.datetime_device)) - this.getTime(new Date(b.datetime_device));
    }
    );
  }

在html中:

  <div class="input-field col s2">
      <mat-checkbox class="example-margin" (click)="sortbydate()">Time</mat-checkbox>
    </div>

到目前为止效果很好

现在,我使用了一个函数,它在间隔 10000 中调用这个函数。 this.getallnotif();

 public notification: Notifications[];
  ngOnInit() {
    this.subscription = Observable.interval(10000).subscribe(x => {
      this.getallnotif();
    });

  getallnotif() {
    this.ws.notif().subscribe(
      notification => {
        console.log(notification)
        this.notification = notification;
      }
    );
  }

service.ts

  public notif(): Observable<Notifications[]> {
    let headers = new Headers();
    headers.append('x-access-token', this.auth.getCurrentUser().token);
    return this.http.get(Api.getUrl(Api.URLS.notif), {
      headers: headers
    })
      .map((response: Response) => {
        let res = response.json();
        if (res.StatusCode === 1) {
          this.auth.logout();
        } else{
          return res.StatusDescription.map(notiff => {
            return new Notifications(notiff);
          });
        }

      });
  }

此代码目前有效,事件在此间隔内调用,排序功能,按顺序对日期进行排序。当我单击 sortbydate () 按钮时,我的数据已正确排序,但仅限于 10000 的时间间隔。我希望我的数据在此间隔后保持排序。

请问我该怎么做?

更新:

我试过这个代码

 this.subscription = Observable.interval(10000).subscribe(x => {
    let notification = this.sortbydate();
    if (x >= notification.length) {
      x = notification.length
         }
         console.log(notification0[x]) // data are all of time sorted but new events not show, only when I refresh page. Please any idea why?
         return notification0[x]
     });

您需要使用一个变量来保存通知的排序方式。如果您有的不仅仅是日期,那么除了这个简单的示例之外,您还需要做一些其他的事情。

isSortedByDate = false;

然后当您单击按钮进行排序时,您需要将 属性 设置为 true

public sortbydate() {
    this.isSortedByDate = true;

    this.notification.sort((a, b) => {
        return this.getTime(new Date(a.datetime_device)) - this.getTime(new Date(b.datetime_device));
    });
}

然后,当您收到新通知时,您需要查看此 属性 并进行排序。

this.ws.notif().subscribe(notification => {
    console.log(notification)
    this.notification = notification;

    if (this.isSortedByDate) {
        this.sortbydate();
    }
});

另一方面,在 rxjs 中将 subscribe 嵌套在 subscribe 中被认为是一种反模式。没有第二个 subscribe,您也可以完成同样的事情。事实上,如果你不使用任何 subscribe 是最好的,这样你就不必处理取消订阅(使用异步管道):

private isSorted = false;
private notificationsSubject$ = new Subject<Notifications[]>();
notifications$ = this.getNotifications();

private getNotifications(): Observable<Notifications[]> {
    return Observable.interval(10000)
        .concatMap(() => this.ws.notif())
        .merge(this.notificationsSubject$)
        .map(notifications => this.isSorted ? this.sort(notifications) : notifications);
}

private sort(notifications: Notifications[]): Notifications[] {
    return [...notifications].sort((a, b) => {
        return this.getTime(new Date(a.datetime_device)) - this.getTime(new Date(b.datetime_device));
    });
}

sortByDate(notifications: Notifications[]) {
    this.isSorted = true;
    this.notificationsSubject$.next(notifications);
}

然后在您当前循环通知的模板中,您将需要使用 async 管道。您可以添加一个 <ng-template>,这样您就可以使用 *ngIf 保留排序方法的通知引用,如下所示:

<ng-template *ngIf="notifications$ | async as notifications">
    <divOrWhateverYouHave *ngFor="let notification of notifications"></divOrWhateverYouHave>
    <div class="input-field col s2">
        <mat-checkbox class="example-margin" (click)="sortByDate(notifications)">Time</mat-checkbox>
    </div>
</ng-template>

我整理了一个StackBlitz to show all of this working together.