[Ramda] Refactor a Promise Chain to Function Composition using Ramda
Promise chains can be a powerful way to handle a series of transformations to the results of an async call. In some cases, additional promises are required along the way. In cases where there are no new promises, function composition can reduce the number of dot chained thens you need. In this lesson, we'll look at how to take a promise chain, and reduce it down with function composition.
const deckUrl = 'https://deckofcardsapi.com/api/deck/new/shuffle/?cards=AS,2S,5C,3C,KD,AH,QH,2C,KS,8C'; fetch(deckUrl)
.then(res => res.json())
.then(deck => fetch(`https://deckofcardsapi.com/api/deck/${deck.deck_id}/draw/?count=10`)
.then(res => res.json())
.then(deck => deck.cards)
.then(cards => cards.filter(c => c.suit === 'CLUBS'))
.then(cards => cards.map(c => c.image))
.then(cards => cards.sort((c1, c2) => c1.value - c2.value)))
.then(cards => cards.map(u => `<img width="" src="${u}"/>`).join(''))
.then(imgString => {
document.querySelector('#cards').innerHTML = `<div>${imgString}</div>`
})
We want to use Ramda to improve code:
Using R.prop and R.map:
// from
.then(deck => deck.cards) // to
.then(prop('cards')) // from
.then(cards => cards.map(c => c.image)) //to
.then(map(prop('image')))
Using R.propEq and R.filter:
// from
.then(cards => cards.filter(c => c.suit === 'CLUBS')) //to
.then(filter(propEq('suit', 'CLUBS')))
Using R.sortBy:
// from
.then(cards => cards.sort((c1, c2) => c1.value - c2.value))) // to
.then(sortBy(prop('value'))))
Using R.compose:
// from
.then(cards => cards.map(u => `<img width="" src="${u}"/>`).join('')) // to
.then(compose(join(''), map(u => `<img width="" src="${u}"/>`)))
Now it looks like:
const {prop, filter, map, sortBy, propEq, join, compose, pluck} = R
const deckUrl = 'https://deckofcardsapi.com/api/deck/new/shuffle/?cards=AS,2S,5C,3C,KD,AH,QH,2C,KS,8C'
fetch(deckUrl)
.then(res => res.json())
.then(deck => fetch(`https://deckofcardsapi.com/api/deck/${deck.deck_id}/draw/?count=10`)
.then(res => res.json())
.then(prop('cards'))
.then(filter(propEq('suit', 'CLUBS')))
.then(map(prop('image')))
.then(sortBy(prop('value')))
.then(compose(join(''), map(u => `<img width="" src="${u}"/>`)))
.then(imgString => {
document.querySelector('#cards').innerHTML = `<div>${imgString}</div>`
})
We can also pull out each step as a function.
const {prop, filter, map, sortBy, propEq, join, compose, pluck} = R
const deckUrl = 'https://deckofcardsapi.com/api/deck/new/shuffle/?cards=AS,2S,5C,3C,KD,AH,QH,2C,KS,8C'
const getId = prop('deck_id');
const drawCards = id => fetch(`https://deckofcardsapi.com/api/deck/${id}/draw/?count=10`)
.then(res => res.json());
const getCards = prop('cards');
const justClubs = filter(propEq('suit', 'CLUBS'));
const sortByValue = sortBy(prop('value'));
const getImages = map(prop('image'));
const toImgString = compose(join(''), map(u => `<img width="" src="${u}"/>`));
const render = imgString => {
document.querySelector('#cards').innerHTML = `<div>${imgString}</div>`
};
fetch(deckUrl)
.then(res => res.json())
.then(getId)
.then(drawCards)
.then(getCards)
.then(justClubs)
.then(getImages)
.then(sortByValue)
.then(toImgString)
.then(render);
Using R.pluck to replace R.map(R.prop(''));
const getImages = pluck('image');
const {prop, filter, map, sortBy, propEq, join, compose, pluck} = R
const deckUrl = 'https://deckofcardsapi.com/api/deck/new/shuffle/?cards=AS,2S,5C,3C,KD,AH,QH,2C,KS,8C'
const getId = prop('deck_id');
const drawCards = id => fetch(`https://deckofcardsapi.com/api/deck/${id}/draw/?count=10`)
.then(res => res.json());
const getCards = prop('cards');
const justClubs = filter(propEq('suit', 'CLUBS'));
const sortByValue = sortBy(prop('value'));
const getImages = pluck('image');
const toImgString = compose(join(''), map(u => `<img width="" src="${u}"/>`));
const render = imgString => {
document.querySelector('#cards').innerHTML = `<div>${imgString}</div>`
};
const transformData = compose(toImgString, getImages, sortByValue, justClubs, getCards)
fetch(deckUrl)
.then(res => res.json())
.then(getId)
.then(drawCards)
.then(compose(render, transformData));
[Ramda] Refactor a Promise Chain to Function Composition using Ramda的更多相关文章
- [Ramda] Convert a QueryString to an Object using Function Composition in Ramda
In this lesson we'll use a handful of Ramda's utility functions to take a queryString full of name/v ...
- [Ramda] Refactor to a Point Free Function with Ramda's useWith Function
Naming things is hard and arguments in generic utility functions are no exception. Making functions ...
- [Typescript] Promise based delay function using async / await
Learn how to write a promise based delay function and then use it in async await to see how much it ...
- [Javascript] Understand Function Composition By Building Compose and ComposeAll Utility Functions
Function composition allows us to build up powerful functions from smaller, more focused functions. ...
- [Ramda] Convert a Promise.all Result to an Object with Ramda's zip and zipObj
In this lesson, we'll use Promise.all to get an array that contains the resolved values from multipl ...
- [Ramda] Refactor to Point Free Functions with Ramda using compose and converge
In this lesson we'll take some existing code and refactor it using some functions from the Ramda lib ...
- Function Composition vs Object Composition
In functional programming, we create large functions by composing small functions; in object-oriente ...
- [Ramda] Create a Query String from an Object using Ramda's toPairs function
In this lesson, we'll use Ramda's toPairs function, along with map, join, concatand compose to creat ...
- [Ramda] Filter an Array Based on Multiple Predicates with Ramda's allPass Function
In this lesson, we'll filter a list of objects based on multiple conditions and we'll use Ramda's al ...
随机推荐
- WebService学习总结(2)——WebService是什么?
一.WebService是什么? 1. 基于Web的服务:服务器端整出一些资源让客户端应用访问(获取数据) 2. 一个跨语言.跨平台的规范(抽象) 3. 多个跨平台.跨语言的应用间通信整合的方案(实际 ...
- Library Component Properties的表格如何填写
- 【Codeforces Round #433 (Div. 2) B】Maxim Buys an Apartment
[链接]h在这里写链接 [题意] 你有n个位置,然后其中有k个地方是已经被人占据了的. 一个"好的位置"的定义是指,这个位置相邻的地方其中至少有一个被人占据了. k个被人占据的位置 ...
- css选择器.md
css选择器总结 1.元素选择器 如:*{},body{},p{} ; xml中note{},to{},from{} 2.class与id选择器 如:.class{},#id{} 3.伪类选择器 选择 ...
- 2、HZK和FreeType的使用
HZK16汉字库的使用 定义如下: unsigned char str[]="我" 在运行时str被初始化为2个字节长度,内容为“我”的GBK码,为:0xCE(区码),0xD2(位 ...
- [Preact] Integrate react-router with Preact
React-router is the community favourite routing solution - it can handle all of your complex routing ...
- 【数学】概念的理解 —— 有序对(ordered pair)
有序对 (a,b) 是一组对象,不同的顺序意味着不同的对象,(a,b)≠(b,a) 除非 a=b,正是因为对象的相对顺序是有着不同含义的,因此有时也称之为 2 维向量.与之相对的无序对(unorder ...
- Linux 下配置 Python IDE——Emacs
工欲善其事,必先利其器.Python作为高级语言,因为其简介.灵活已经被越来越多的程序员所青睐.在尝试了众多IDE之后,终于找到了自己的挚爱.废话少说,下面开始说一下如何在linux下安装配置Emac ...
- or小计
1.使用or的时候,必须养成两边添加括号,否则结果完全不一样. 2.or条件如果复杂的情况下,可以适当考虑union all改写.
- UILabel调整字间距
1.引入 在文件导入 #import <CoreText/CoreText.h> 2.程序 NSMutableAttributedString *attributedString =[[N ...