30 天精通 RxJS (13): Observable Operator - delay, delayWhen

在全部非同步中行爲中,最麻煩的大概就是 UI 操做了,由於 UI 是直接影響使用者的感覺,若是處理的很差對使用體驗會大大的扣分!javascript

UI 大概是全部非同步行爲中最很差處理的,不僅是由於它直接影響了用戶體驗,更大的問題是 UI 互動經常是高頻率觸發的事件,並且多個元件間的時間序須要不一致,要作到這樣的 UI 互動就不太可能用 Promise 或 async/await,可是用 RxJS 仍然能輕易地處理!css

今天咱們要介紹的兩個 Operators,delay 跟 delayWhen 都是跟 UI 互動比較相關的。當咱們的網頁愈來愈像應用程式時,UI 互動就變得越重要,讓咱們來試試如何用 RxJS 完成基本的 UI 互動!html

Operators

delay

delay 能夠延遲 observable 一開始發送元素的時間點,示例以下java

var source = Rx.Observable.interval(300).take(5);

var example = source.delay(500);

example.subscribe({
    next: (value) => { console.log(value); },
    error: (err) => { console.log('Error: ' + err); },
    complete: () => { console.log('complete'); }
});
// 0
// 1
// 2
// 3
// 4複製代碼

JSBin | JSFiddlebash

固然直接從 log 出的訊息看,是徹底看不出差別的async

讓咱們直接看 Marble Diagram優化

source : --0--1--2--3--4|
        delay(500)
example: -------0--1--2--3--4|複製代碼

從 Marble Diagram 能夠看得出來,第一次送出元素的時間變慢了,雖然在這裏看起來沒什麼用,可是在 UI 操做上是很是有用的,這個部分咱們最後示範。ui

delay 除了能夠傳入毫秒之外,也能夠傳入 Date 型別的資料,以下使用方式spa

var source = Rx.Observable.interval(300).take(5);

var example = source.delay(new Date(new Date().getTime() + 1000));

example.subscribe({
    next: (value) => { console.log(value); },
    error: (err) => { console.log('Error: ' + err); },
    complete: () => { console.log('complete'); }
});複製代碼

JSBin | JSFiddle.net

這好像也能用在預約某個日期,讓程式掛掉233

delayWhen

delayWhen 的做用跟 delay 很像,最大的差異是 delayWhen 能夠影響每一個元素,並且須要傳一個 callback 並回傳一個 observable,示例以下

var source = Rx.Observable.interval(300).take(5);

var example = source
              .delayWhen(
                  x => Rx.Observable.empty().delay(100 * x * x)
              );

example.subscribe({
    next: (value) => { console.log(value); },
    error: (err) => { console.log('Error: ' + err); },
    complete: () => { console.log('complete'); }
});複製代碼

JSBin | JSFiddle

這時咱們的 Marble Diagram 以下

source : --0--1--2--3--4|
    .delayWhen(x => Rx.Observable.empty().delay(100 * x * x));
example: --0---1----2-----3-----4|複製代碼

這裏傳進來的 x 就是 source 送出的每一個元素,這樣咱們就能對每個作延遲。

這裏咱們用 delay 來作一個小功能,這個功能很簡單就是讓多張照片跟着滑鼠跑,但每張照片不能跑同樣快!

首先咱們準備六張大頭照,而且寫進 HTML

<img src="https://res.cloudinary.com/dohtkyi84/image/upload/c_scale,w_50/v1483019072/head-cover6.jpg" alt="">
<img src="https://res.cloudinary.com/dohtkyi84/image/upload/c_scale,w_50/v1483019072/head-cover5.jpg" alt="">
<img src="https://res.cloudinary.com/dohtkyi84/image/upload/c_scale,w_50/v1483019072/head-cover4.jpg" alt="">
<img src="https://res.cloudinary.com/dohtkyi84/image/upload/c_scale,w_50/v1483019072/head-cover3.jpg" alt="">
<img src="https://res.cloudinary.com/dohtkyi84/image/upload/c_scale,w_50/v1483019072/head-cover2.jpg" alt="">
<img src="https://res.cloudinary.com/dohtkyi84/image/upload/c_scale,w_50/v1483019072/head-cover1.jpg" alt="">複製代碼

用 CSS 把 img 改爲圓形,並加上邊筐以及絕對位置

img{
  position: absolute;
  border-radius: 50%;
  border: 3px white solid;
  transform: translate3d(0,0,0);
}複製代碼

再來寫 JS,同樣第一步先抓 DOM

var imgList = document.getElementsByTagName('img');複製代碼

第二步創建 observable

var movePos = Rx.Observable.fromEvent(document, 'mousemove')
.map(e => ({ x: e.clientX, y: e.clientY }))複製代碼

第三步撰寫邏輯

function followMouse(DOMArr) {
  const delayTime = 600;
  DOMArr.forEach((item, index) => {
    movePos
      .delay(delayTime * (Math.pow(0.65, index) + Math.cos(index / 4)) / 2)
      .subscribe(function (pos){
        item.style.transform = 'translate3d(' + pos.x + 'px, ' + pos.y + 'px, 0)';
      });
  });
}

followMouse(Array.from(imgList))複製代碼

這裏咱們把 imgList 從 Collection 轉成 Array 後傳入 followMouse(),並用 forEach 把每一個 omg 取出並利用 index 來達到不一樣的 delay 時間,這個 delay 時間的邏輯你們能夠本身想,不用跟我同樣,最後 subscribe 就完成啦!

最後完整的示例在這裏

今日小結

今天咱們介紹了兩個 operators 並帶了一個小示例,這兩個 operators 在 UI 操做上都很是的實用,咱們明天會接着講幾個 operators 能夠用來作高頻率觸發的事件優化!

相關文章
相關標籤/搜索