以下是我试图组成单个端点字符串的四个函数:
const endpoint = str => `${str}` || 'default'
const protocol = str => `https://${str}`
const params = str => `${str}?sort=desc&part=true&`
const query = str => `${str}query={ some:'value', another:'value'}`
let finalEndpoint = R.compose(query, params, protocol, endpoint)
var result = finalEndpoint('api.content.io')
这个组合工作并返回我想要的结果:
https://api.content.io?sort=desc&part=true&query={ some:'value', another:'value'}
但请注意我的函数体中params
和query
的硬编码值。我看到只有一个值超过了此R.compose
链中的值。
我如何以及在何处将参数传递给参数和查询参数?
更新:
我所做的是对这些功能进行了调整:
var R = require('ramda');
const endpoint = str => `${str}` || 'default'
const protocol = str => `https://${str}`
const setParams = R.curry ( (str, params) => `${str}?${params}` )
const setQuery = R.curry ( (str, query) => `${str}&query=${JSON.stringify(query)}` )
然后
let finalEndpoint = R.compose(protocol, endpoint)
var result = setQuery(setParams(finalEndpoint('api.content.io'), 'sort=desc&part=true'), { some:'value', another:'value'})
console.log(result);
但是获得result
的最终调用仍然看起来非常黑,而且不够优雅。有没有办法改善这个?
答案 0 :(得分:6)
我如何以及在何处将参数传递给参数和查询参数?
老实说,你没有,不是在你用Ramda或类似的库构建compose
或pipe
管道时。
Ramda(免责声明:我是其中一位作者)允许第一个函数接收多个参数 - 其他一些函数执行,有些则没有 - 但后续函数只接收先前调用的结果。 Sanctuary,meld
中有一个函数可能对此有所帮助,但它确实有一个相当复杂的API。
但是,我真的不明白为什么你首先以这种方式构建这个功能。这些中间函数是否实际可重用,或者您是否按规范构建它们?我问的原因是,这似乎是同一个想法的一个更合理的版本:
const finalEndpoint = useWith(
(endpoint, params, query) =>`https://${endpoint}?${params}&query=${query}`, [
endpoint => endpoint || 'default',
pipe(toPairs, map(join('=')), join('&')),
pipe(JSON.stringify, encodeURIComponent)
]
);
finalEndpoint(
'api.content.io',
{sort: 'desc', part: true},
{some:'value', another:'value'}
);
//=> "https://api.content.io?sort=desc&part=true&query=%7B%22some%22%3A%22value%22%2C%22another%22%3A%22value%22%7D"
我真的不知道你对最后一个参数的要求。没有encodeUriComponent
,我看起来很奇怪,但也许你不需要它。我还对第二个参数采取了自由,假设您更喜欢API中的实际数据到封装该数据的字符串。但是,如果您希望传递'sort=desc&part=true'
,请将pipe(toPairs, map(join('=')), join('&'))
替换为identity
。
由于整个事情远非无点,我没有使用第一个函数的无点版本,可能是or(__, 'default')
,因为我认为它更具可读性。
<强>更新强>
您可以在 Ramda REPL 上看到此版本,该版本会在tap
处添加一些console.log
语句。
这确实为Ramda提出了一个有趣的问题。如果这些中间函数确实是可取的,那么Ramda无法将它们组合起来。显然Ramda可以提供类似meld
的东西,但是有中间地位吗?我想知道是否有一个有用的功能(当然是咖喱),我们应该包括像
someFunc([f0], [a0]); //=> f0(a0)
someFunc([f0, f1], [a0, a1]); //=> f1(f0(a0), a1)
someFunc([f0, f1, f2], [a0, a1, a2]); //=> f2(f1(f0(a0), a1), a2)
someFunc([f0, f1, f2, f3], [a0, a1, a2, a3]); //=> f3(f2(f1(f0(a0), a1), a2), a3)
// ...
有一些严重的反对意见:如果列表长度不同会怎么样?为什么初始调用是一元的,我们应该通过向函数添加单独的累加器参数来解决这个问题吗?尽管如此,这是一个有趣的功能,我可能会提出它来讨论Ramda主板。
答案 1 :(得分:1)
我为这种情况写了a little helper function。
就像compose,但是其余的参数也传入。第一个参数是前一个函数的返回值。其余的参数保持不变。
有了它,您可以按如下方式重写代码:
const compound = require('compound-util')
const endpoint = str => `${str}` || 'default'
const protocol = str => `https://${str}`
const params = (str, { params }) => `${str}?${params}`
const query = (str, { query }) => `${str}query=${query}`
const finalEndpoint = compound(query, params, protocol, endpoint)
const result = finalEndpoint('api.content.io', {
params: 'sort=desc&part=true&',
query: JSON.stringify({ some:'value', another:'value'})
})
答案 2 :(得分:0)
如果你有params并查询curried函数,那么你可以:
编辑:包含所有花里胡哨的代码,需要更改参数顺序或使用R.__
和字符串化对象
const endpoint = R.curry( str => `${str}` || 'default' )
const protocol = R.curry( str => `https://${str}` )
const params = R.curry( (p, str) => `${str}?${p}` )
const query = R.curry( (q, str) => `${str}&query=${q}` )
let finalEndpoint =
R.compose(
query(JSON.stringify({ some:'value', another:'value' })),
params('sort=desc&part=true'),
protocol,
endpoint
)
var result = finalEndpoint('api.content.io')
console.log(result)