ایجاد تایمرهای متوالی و بیوقفه
با استفاده از عملگر Observable.interval میتوان یک تایمر بینهایت را ایجاد کرد. پارامتر ورودی آن بر حسب میلی ثانیه است و مشترکین به آن در بازههای زمانی مشخص شدهی توسط این پارامتر، عدد جاری این بازه را دریافت میکنند.
یک مثال:
در این مثال میخواهیم تایمری را ایجاد کنیم که هر ثانیه یکبار، کدی را اجرا کند:
import { Observable } from "rxjs/Observable"; import "rxjs/add/observable/interval"; import { Subscription } from "rxjs/Subscription"; @Component() export class UsingTimersComponent { private intervalSubscription: Subscription; interval = 0; startInterval() { const interval = Observable.interval(1000); this.intervalSubscription = interval.subscribe(i => this.interval += i); } stopInterval() { this.intervalSubscription.unsubscribe(); } }
<div class="panel panel-default"> <div class="panel-heading"> <h2 class="panel-title">Observable.interval(1000)</h2> </div> <div class="panel-body"> <div> <label>interval: </label> {{interval}} </div> <div> <button (click)="startInterval()" class="btn btn-success">Start</button> <button (click)="stopInterval()" class="btn btn-danger">Stop</button> </div> </div> </div>
پس از آن فراخوانی Observable.interval(1000) یک Observable را ایجاد میکند که توانایی صدور رخدادهایی را در بازههای زمانی متوالی 1000 میلی ثانیهای، دارا است.
اکنون مشترکین به آن، اعداد متوالی شروع شدهی از صفر را در هر ثانیه یکبار، دریافت میکنند:
this.intervalSubscription = interval.subscribe(i => this.interval += i);
this.intervalSubscription.unsubscribe();
مطلع شدن از پایان کار یک تایمر
با استفاده از اپراتور finally که از مسیر rxjs/add/operator/finally قابل import است، میتوان رخداد لغو اشتراک به این Observable و یا همان خاتمهی تایمر را در اینجا دریافت کرد:
this.intervalSubscription = interval .finally(() => console.log("All done!")) .subscribe(i => this.interval += i);
ایجاد تایمرهای خود متوقف شونده
با استفاده از عملگر Observable.timer که در مسیر rxjs/add/observable/timer قرار دارد، میتوان تایمری را ایجاد کرد که پس از یک تاخیر مشخص شده، اجرا شود و بلافاصله خاتمه یابد:
const timer = Observable.timer(1000); timer.subscribe(data => console.log('ding!'));
این تایمر امکان اجرای در بازههای زمانی مشخصی را نیز دارا است:
const moreThanOne$ = Observable.timer(2000, 500); moreThanOne$.subscribe(data => console.log('timer with args', data));
محدود کردن تعداد بار اجرای تایمر
اگر Observable.timer با پارامتر دوم آن بکار رود، بینهایت بار اجرا خواهد شد. اما میتوان این تعداد بار اجرا را توسط اپراتور take که از مسیر rxjs/add/operator/take قابل import است، محدود کرد:
let moreThanOne$ = Observable.timer(2000, 500).take(3); moreThanOne$.subscribe(data => console.log('timer with args', data));
اجرای با تاخیر بازههای زمانی
با استفاده از اپراتور delay که از مسیر rxjs/add/operator/delay قابل import است، میتوان هر بار اجرای callback تایمر را با یک تاخیر دریافت کرد:
const start = new Date(); const stream$ = Observable.interval(500).take(3); stream$.delay(300).subscribe(x => { console.log('val',x); console.log( new Date() - start ); })
val:0 800ms val:1 1300ms val:2 1800ms
ایجاد یک تایمر شمارش معکوس
فرض کنید میخواهید تایمری را ایجاد کنید که در طی یک شمارش معکوس، از عدد 10000 شروع شود و هر ثانیه یکبار 1000 واحد از آن کاهش یابد و زمانیکه به صفر رسید، متوقف شود.
این تایمر پس از import وابستگیهای آن:
import { Observable } from "rxjs/Observable"; import "rxjs/add/observable/timer"; import "rxjs/add/operator/finally"; import "rxjs/add/operator/takeUntil"; import "rxjs/add/operator/map";
const interval = 1000; const duration = 10 * 1000; const stream$ = Observable.timer(0, interval) .finally(() => console.log("All done!")) .takeUntil(Observable.timer(duration + interval)) .map(value => duration - value * interval); stream$.subscribe(value => console.log(value));
در اینجا چون اعداد صادر شدهی از طرف تایمر، افزایشی هستند، نیاز است به روشی آنها را تغییر داد. در یک چنین حالتی از اپراتور map استفاده میشود. در اینجا value، هربار مقدار افزایشی شروع شدهی از صفر را ارائه میدهد. توسط عملگر map، این خروجی افزایشی را به یک خروجی کاهشی تبدیل کردهایم تا بتوان به یک تایمر شمارش معکوس رسید.
دریافت مدت زمان بین اجرای بازههای زمانی
Observable.timer با هر بار اجرا، اعداد شروع شدهی از صفر را به مشترکین ارسال میکند. اگر در این بین از اپراتور timeInterval قرار گرفتهی در مسیر rxjs/add/operator/timeInterval استفاده شود، این مقدار ارسالی از نوع مخصوص <TimeInterval<number خواهد بود که دارای خواص value و interval است:
const source = Observable.timer(0, 1000) .timeInterval() .map(x => x.value + ":" + x.interval) .take(5); const subscription = source.subscribe( x => console.log("Next timeInterval: " + x), err => console.log("Error: " + err), () => console.log("Completed") );
در این مثال با استفاده از متد map، یک خروجی سفارشی تهیه شدهاست. اگر صرفا علاقمند به دریافت مقدار خاصیت interval باشید، میتوان به صورت ذیل نیز عمل کرد:
const source = Observable.timer(0, 1000) .timeInterval() .pluck("interval") .take(5);
تعلیق و از سرگیری مجدد تایمرها
با قطع اشتراک از یک منبع تایمر، سبب توقف کامل آن خواهیم شد. اما اگر برای مدتی بخواهیم آنرا در حالت تعلیق قرار دهیم، میتوان به صورت ذیل عمل کرد:
import { Observable } from "rxjs/Observable"; import "rxjs/add/observable/never"; import "rxjs/add/observable/timer"; import { Subject } from "rxjs/Subject"; tick: number; pauser = new Subject(); tickerSource = new Subject(); startTicker() { Observable.timer(0, 1000) .subscribe(this.tickerSource); this.pauser .switchMap(paused => paused ? Observable.never() : this.tickerSource). subscribe(t => this.tickerFunc(t)); this.pauser.next(false); // resume } tickerFunc(tick) { this.tick = tick; } pauseTicker() { this.pauser.next(true); } resumeTicker() { this.pauser.next(false); }
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید.