角度延迟,暂停并在停止的地方重新开始

时间:2018-12-19 14:26:31

标签: angular

我从角度开始,我尝试制作一个场景,该场景显示有延迟的消息,并具有根据消息暂停等待消息响应的能力。

我设法显示该消息,但是暂停功能,等待答案并重新启动或方案被停止的功能给我带来了比我想象的更多的麻烦。

我以为我可能会使用Observable或Promise,但是我对这些功能并不熟悉,并且文档并没有太大帮助。

如果您能告诉我怎么做或给我看一个类似的例子,我会很高兴的。

这是仅以基本方式显示消息的代码。

scenario.ts

import {Message} from "./message";

export class Scenario {
  id: number;
  messages: Array<Message>;
}

message.ts

export class Message {
  id: number;
  message: string;
  delay: number;
  wait: boolean;
  type: string;
}

mock-scenario.ts

import {Scenario} from "./scenario";

export const SCENARIOS: Scenario[] = [
  {
    id      : 1,
    messages: [
      {id: 1, message: 'Message 1', delay: 5, wait: false, type: ''},
      {id: 2, message: 'Message 2', delay: 5, wait: false, type: ''},
      {id: 3, message: 'Message 3', delay: 5, wait: true, type: 'text'},
      {id: 4, message: 'Message 4', delay: 5, wait: true, type: 'text'},
      {id: 5, message: 'Message 5', delay: 5, wait: true, type: 'date'},
      {id: 6, message: 'Message 6', delay: 5, wait: true, type: 'email'},
      {id: 7, message: 'Message 7', delay: 5, wait: false, type: ''},
      {id: 8, message: 'Message 8', delay: 5, wait: true, type: 'text'},
      {id: 9, message: 'Message 9', delay: 5, wait: true, type: 'tel'}
    ]
  }
];

ApiTchatLibService.ts

getScenarios(): Observable<Scenario[]> {
    return of(SCENARIOS);
}

getScenario(id: number): Observable<Scenario> {
    return of(SCENARIOS.find(scenario => scenario.id === id));
}

getMessages(id: number): Observable<Message[]> {
    return of(SCENARIOS.find(scenario => scenario.id === id).messages);
}

ApiTchatLibComponent.ts

import {Component, OnInit} from '@angular/core';
import {ApiTchatLibService} from "./api-tchat-lib.service";
import {Message} from "./message";

@Component({
  selector: 'atl-api-tchat-lib',
  template: `
    <p *ngFor="let message of messages" data-id="{{message.id}}">{{message.message}}</p>
  `,
  styles  : []
})
export class ApiTchatLibComponent implements OnInit {

  messages: Array<Message> = [];
  isWaiting: boolean = false;

  constructor(private apiTchatLibService: ApiTchatLibService) {
  }

  getMessages() {
    this.apiTchatLibService.getMessages(1).subscribe(messages => {
        from(messages).pipe(
            concatMap(item => of(item).pipe(
                delay(item.delay * 1000)
            ))
        ).subscribe((r) => {
            this.messages.push(r);
        });
    });
  }

  ngOnInit() {
    this.getMessages();
  }
}

2 个答案:

答案 0 :(得分:1)

您可以通过rxjs轻松实现。

示例代码块

from([ { delay: 1000, message: 'A'} , { delay: 2000 , message: 'B'}, { delay: 3000 , message: 'C'} ]).pipe(
  concatMap( item => of(item).pipe( delay( item.delay ) )) 
).subscribe((r) => {
  console.log(r.message);
});

延迟代码

import { concatMap, delay } from 'rxjs/operators';
import { of, from } from 'rxjs';

    getMessages() {
        this.apiTchatLibService.getMessages(1).subscribe(messages => {


       from(messages).pipe(
          concatMap( item => of(item).pipe( delay( item.delay ) )) 
       ).subscribe((r) => {
         this.messages.push(r.message)
       });

     }

我们在这里创建一个可观察到的延迟。 concatMap将帮助您将消息排队。

开始/暂停代码:您可以将对象一直等到剩下的时间再移至数组。

import { concatMap, delay } from 'rxjs/operators';
import { of, from } from 'rxjs';

class YourClass {
  nextIteration = [];
  messages = [];

  getMessages() {
    this.apiTchatLibService.getMessages(1).subscribe(messages => {
      from(this.start(messages))
        .pipe(concatMap(item => of(item).pipe(delay(item.delay))))
        .subscribe(r => {
          this.messages.push(r.message);
        });
    });
  }

  getNextList(messages) {
    this.nextIteration = [];
    let flag = true;
    let obsMessages = [];
    for (let message of messages) {
      if (flag) {
        obsMessages = [...obsMessages, message];
      } else {
        this.nextIteration = [...this.nextIteration, message];
      }
      if (message.wait) {
        flag = false;
      }
    }
    return obsMessages;
  }

  start(messages) {
    from(this.getNextList(messages))
      .pipe(concatMap(item => of(item).pipe(delay(item.delay))))
      .subscribe(r => {
        console.log(r.message);
      });
  }

  resume() {
    this.start(this.nextIteration);
  }

}


<button (click)="resume()">Start</button>

答案 1 :(得分:0)

@rijin建议延迟的好方法,我会避免嵌套订阅。

getMessages() {


  this.apiTchatLibService
  .getMessages(1)
  .pipe(
    concatMap(messages => from(messages).pipe(delay(message => message.delay)))
  )
  .subscribe(() => {
    this.messages.push(message);
  });
}

如果要暂停/继续,则需要将resume $流传递给此方法。当您需要恢复时,只需将事件放入resume $流中即可。

getMessages() {
  this.apiTchatLibService.getMessages(1).pipe(
    concatMap(messages => from(messages).pipe(
       delayWhen(message => message.wait ? this.resume$ : timer(item.delay))
    )
  ).subscribe((r) => {
   this.messages.push(r.message)
  });
}