一段時間的響應式程式設計的研究,對Rxjs有了一些熟悉。雖然工作中絕大部分時候很少會有複雜的需求用到Rxjs,但是對於Rxjs的思想和響應式程式設計、觀察者模式等相關知識是值得學習的!
而且其中的觀察者模式Observable已經列入了JavaScript規範中。Observable 目前處於 stage 1,但它已被 TC39 委員會標記為 “ready to advance” 並獲得了瀏覽器廠商的大力支援,因此有望很快推進到下一階段。
從Rxjs的operators移植一些到日常開發中的可復現場景。
1.合併陣列concatAll
Array.prototype.concatAll = function () {
let results = [];
this.forEach((subArray) => {
results.push.apply(results, subArray);
});
return results;
};
console.log(JSON.stringify([[1, 2, 3], [4, 5, 6], [7, 8, 9]].concatAll()))
//[1,2,3,4,5,6,7,8,9]
複製程式碼
當然,js陣列的concat方法也可實現,eg
console.log(JSON.stringify([1, 2, 3].concat([4, 5, 6], [7, 8, 9])))
//[1,2,3,4,5,6,7,8,9]
複製程式碼
但concatAll是為擴充套件後文的幾個operator而重新定義的合併陣列的方法,看後文
2.concatMap
concatMap:map()+concatAll()
Array.prototype.concatMap = function (projectionFunctionThatReturnsArray) {
return this.map(function (item) {
return projectionFunctionThatReturnsArray(item);
}).
// 使用concatAll方法來打平陣列
concatAll();
};
let spanishFrenchEnglishWords = [["cero", "rien", "zero"], ["uno", "un", "one"], ["dos", "deux", "two"]];
// map返回三個陣列,concatAll返回打平後的一個陣列
let allWords = [0, 1, 2].
concatMap(index => spanishFrenchEnglishWords[index]);
console.log(JSON.stringify(allWords))
// ["cero","rien","zero","uno","un","one","dos","deux","two"]
複製程式碼
常用場景:打平陣列,獲取陣列中的深層資料,eg:
let movieLists = [
{
name: "Instant Queue",
videos: [
{
"id": 70111470,
"title": "Die Hard",
"boxarts": [
{ width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/DieHard150.jpg" },
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/DieHard200.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 4.0,
"bookmark": []
},
{
"id": 654356453,
"title": "Bad Boys",
"boxarts": [
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg" },
{ width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys150.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 5.0,
"bookmark": [{ id: 432534, time: 65876586 }]
}
]
},
{
name: "New Releases",
videos: [
{
"id": 65432445,
"title": "The Chamber",
"boxarts": [
{ width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber150.jpg" },
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 4.0,
"bookmark": []
},
{
"id": 675465,
"title": "Fracture",
"boxarts": [
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg" },
{ width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture150.jpg" },
{ width: 300, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 5.0,
"bookmark": [{ id: 432534, time: 65876586 }]
}
]
}
];
const data = movieLists.concatMap((movieList) => {
return movieList.videos.concatMap((video) => {
return video.boxarts.
filter((boxart) => boxart.width === 150 && boxart.height === 200).
map((boxart) => {
return { id: video.id, title: video.title, boxart: boxart.url };
});
});
});
console.log(JSON.stringify(data))
/* [
{"id":70111470,"title":"Die Hard","boxart":"http://cdn-0.nflximg.com/images/2891/DieHard150.jpg"},
{"id":654356453,"title":"Bad Boys","boxart":"http://cdn-0.nflximg.com/images/2891/BadBoys150.jpg"},
{"id":65432445,"title":"The Chamber","boxart":"http://cdn-0.nflximg.com/images/2891/TheChamber150.jpg"},
{"id":675465,"title":"Fracture","boxart":"http://cdn-0.nflximg.com/images/2891/Fracture150.jpg"}
]
*/
複製程式碼
3.reduceArray
即reduce並返回陣列,為的是能鏈式呼叫,以結合map等方法
// [1,2,3].reduceArray(function(accumulatedValue, currentValue) { return accumulatedValue + currentValue; }); === [6];
// [1,2,3].reduceArray(function(accumulatedValue, currentValue) { return accumulatedValue + currentValue; }, 10); === [16];
Array.prototype.reduceArray = function (combiner, initialValue) {
let counter,
accumulatedValue;
if (this.length === 0) {
return this;
}
else {
if (arguments.length === 1) {
counter = 1;
accumulatedValue = this[0];
}
else if (arguments.length >= 2) {
counter = 0;
accumulatedValue = initialValue;
}
else {
throw "Invalid arguments.";
}
while (counter < this.length) {
accumulatedValue = combiner(accumulatedValue, this[counter])
counter++;
}
return [accumulatedValue];
}
};
let movieLists = [
{
name: "New Releases",
videos: [
{
"id": 70111470,
"title": "Die Hard",
"boxarts": [
{ width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/DieHard150.jpg" },
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/DieHard200.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 4.0,
"bookmark": []
},
{
"id": 654356453,
"title": "Bad Boys",
"boxarts": [
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg" },
{ width: 140, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 5.0,
"bookmark": [{ id: 432534, time: 65876586 }]
}
]
},
{
name: "Thrillers",
videos: [
{
"id": 65432445,
"title": "The Chamber",
"boxarts": [
{ width: 130, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg" },
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 4.0,
"bookmark": []
},
{
"id": 675465,
"title": "Fracture",
"boxarts": [
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg" },
{ width: 120, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture120.jpg" },
{ width: 300, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 5.0,
"bookmark": [{ id: 432534, time: 65876586 }]
}
]
}
];
/* 使用concatMap,map,reduceArray來生成以下陣列,注:返回的是width*height最小的
[
{"id": 675465,"title": "Fracture","boxart":"http://cdn-0.nflximg.com/images/2891/Fracture120.jpg" },
{"id": 65432445,"title": "The Chamber","boxart":"http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg" },
{"id": 654356453,"title": "Bad Boys","boxart":"http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg" },
{"id": 70111470,"title": "Die Hard","boxart":"http://cdn-0.nflximg.com/images/2891/DieHard150.jpg" }
]; */
const data = movieLists.concatMap(type => {
return type.videos.concatMap(video => {
return video.boxarts.reduceArray((prev, next) => {
return (prev.width * prev.height < next.width * next.height) ? prev : next;
}).map(boxart => {
return { id: video.id, title: video.title, boxart: boxart.url }
})
})
})
console.log(data)
複製程式碼
4.zip
給陣列新增一個靜態方法zip(),zip接收三個引數(第一個陣列的元素,第二個陣列中與第一個陣列index相同的元素,對此兩個元素進行的操作).由於zip方法需要2個陣列中各自的一個元素,所以zip方法返回的元素個數與輸入的兩個陣列中的短陣列length相同
// JSON.stringify(Array.zip([1,2,3],[4,5,6,7,8], function(left, right) { return left + right })) === `[5,7,9]`
Array.zip = function (left, right, combinerFunction) {
let counter,
results = [];
for (counter = 0; counter < Math.min(left.length, right.length); counter++) {
results.push(combinerFunction(left[counter], right[counter]));
}
return results;
};
複製程式碼
zip()常用於組合兩個陣列,返回的陣列由輸入的兩個陣列中的元素組成,eg:
let movieLists = [
{
name: "New Releases",
videos: [
{
"id": 70111470,
"title": "Die Hard",
"boxarts": [
{ width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/DieHard150.jpg" },
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/DieHard200.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 4.0,
"interestingMoments": [
{ type: "End", time: 213432 },
{ type: "Start", time: 64534 },
{ type: "Middle", time: 323133 }
]
},
{
"id": 654356453,
"title": "Bad Boys",
"boxarts": [
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg" },
{ width: 140, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 5.0,
"interestingMoments": [
{ type: "End", time: 54654754 },
{ type: "Start", time: 43524243 },
{ type: "Middle", time: 6575665 }
]
}
]
},
{
name: "Instant Queue",
videos: [
{
"id": 65432445,
"title": "The Chamber",
"boxarts": [
{ width: 130, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg" },
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 4.0,
"interestingMoments": [
{ type: "End", time: 132423 },
{ type: "Start", time: 54637425 },
{ type: "Middle", time: 3452343 }
]
},
{
"id": 675465,
"title": "Fracture",
"boxarts": [
{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg" },
{ width: 120, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture120.jpg" },
{ width: 300, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg" }
],
"url": "http://api.netflix.com/catalog/titles/movies/70111470",
"rating": 5.0,
"interestingMoments": [
{ type: "End", time: 45632456 },
{ type: "Start", time: 234534 },
{ type: "Middle", time: 3453434 }
]
}
]
}
];
const data = movieLists.concatMap(movieList => {
return movieList.videos.concatMap(video => {
return Array.zip(
video.boxarts.reduceArray((acc, curr) => {
return (acc.width * acc.height < curr.width * curr.height) ? acc : curr;
}),
video.interestingMoments.filter(interestingMoment => {
return interestingMoment.type === "Middle";
}),
(boxart, interestingMoment) => {
return { id: video.id, title: video.title, time: interestingMoment.time, url: boxart.url };
});
});
});
console.log(JSON.stringify(data))
/*
[{"id":70111470,"title":"Die Hard","time":323133,"url":"http://cdn-0.nflximg.com/images/2891/DieHard150.jpg"},
{"id":654356453,"title":"Bad Boys","time":6575665,"url":"http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg"},
{"id":65432445,"title":"The Chamber","time":3452343,"url":"http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg"},
{"id":675465,"title":"Fracture","time":3453434,"url":"http://cdn-0.nflximg.com/images/2891/Fracture120.jpg"}]
*/
複製程式碼
總結:
從Rxjs上移植過來的4個操作符,可以很好的擴充套件陣列方法及鏈式呼叫,常用場景有:
- 陣列的鏈式呼叫
- 陣列的打平
- 陣列轉換成Object
- 待發掘…
參考: