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的更多相关文章

  1. [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 ...

  2. [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 ...

  3. [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 ...

  4. [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. ...

  5. [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 ...

  6. [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 ...

  7. Function Composition vs Object Composition

    In functional programming, we create large functions by composing small functions; in object-oriente ...

  8. [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 ...

  9. [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 ...

随机推荐

  1. C#string转换为Datetime

    DateTime.ParseExact("0710090000", "MMddHHmmss", CultureInfo.CurrentCulture, Date ...

  2. ASP.NET路径解惑

    对于ASP.NET的路径问题,一直都是云里雾里,没有去详细的理解,今天正好可以梳理一下它们之间的关系和使用方法.而若想明白路径的表示方式的使用方法和区别以及注意事项可以通过下面的几个概念来进一步加深: ...

  3. 关于http请求指定本地ip

    static void Main(string[] args) { //ssl证书验证问题(没有校验) ServicePointManager.ServerCertificateValidationC ...

  4. iOS_04_数据类型、常量、变量

    一.数据 1.什么是数据 * 生活中时时刻刻都在跟数据打交道,比如体重数据.血压数据.股价数据等.在我们使用计算机的过程中,会接触到各种各样的数据,有文档数据,图片数据,视频数据,还有聊天QQ产生的文 ...

  5. Altium Designer如何对齐原件

    右边那个图标是排列菜单

  6. Loadrunner--关联详解

    当录制脚本时,VuGen会拦截client端(浏览器)与server端(网站服务器)之间的对话,并且通通记录下来,产生脚本.在VuGen的Recording Log中,您可以找到浏览器与服务器之间所有 ...

  7. pragma pack,字节对齐

    关于字节对齐 pragma pack 一. 测试代码: // packTest.cpp : Defines the entry point for the console application. / ...

  8. 【Codeforces Round #445 (Div. 2) B】Vlad and Cafes

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 傻逼模拟 [代码] #include <bits/stdc++.h> using namespace std; cons ...

  9. Git 基本使用方法

    Git有一个优点,在本地的每个项目都是一个完整的仓库,除了须要从网络拉取和推送到网络之外,其它全部的操作都能够在本地完毕. 本文简单地介绍怎样在本地使用Git来对文件进行管理,下一篇文章再来说一下分支 ...

  10. libjpeg用法

    libjpeg是一个完全用C语言编写的库,包含了被广泛使用的JPEG解码.JPEG编码和其他的JPEG功能的实现.这个库由独立JPEG工作组维护.最新版本号是6b,于1998年发布.可以参考维基百科关 ...