我目前正在学习JavaScript中的函数式编程。我使用ramda作为帮助程序库来编写诸如asyncPipe
:
import { pipeWith, then } from 'ramda';
export const asyncPipe = pipeWith(then);
要登录用户,我必须使用静态URL进行未经身份验证的提取请求:
export const postRequest = route =>
asyncPipe([
body =>
fetch(route, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
}),
getJSON,
]);
现在,由于url是静态的,因此我可以使用此函数,并在如下所示的管道中使用它:
export const login = asyncPipe([
postRequest(ROUTE_LOGIN),
prop('token'),
setToken,
]); // Will get called with the correct body
到目前为止很好。但是现在我必须使用动态URL和正文进行请求,并且它需要进行身份验证,因此我需要标头。我正在努力编写此代码,以使其易于使用。
这是我尝试过的:
export const postRequestWithAuth = route => body =>
asyncPipe([
getToken,
token =>
fetch(route, {
method: 'POST',
headers: { Authorization: `Token ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify(body),
}),
getJSON,
]);
但是我无法弄清楚如何将其与pipe
或compose
(当然是异步的)一起使用,因为我必须以这种方式编写它:
postRequestWithAuth(ROUTE_HOUSES + uuid)(body)()
,而最后一次调用只是激活asyncPipe
。如您所见,这非常混乱并且很难pipe
。您将如何以实用的方式解决此问题?
ramda非常适合使用JavaScript进行函数式编程,但是对于诸如您这样的情况而言却不足。这是一种使用rubico
编写所需代码的方法import { pipe, fork, get } from 'rubico'
// expects the object { body: {...}, uuid: 'string' }
export const postRequestWithAuth = route => pipe([
fork({
method: () => 'POST',
headers: pipe([
get('uuid'),
getToken,
token => ({
Authorization: `Token ${token}`,
'Content-Type': 'application/json',
}),
]),
body: pipe([
get('body'),
JSON.stringify,
]),
}),
payload => fetch(route, payload),
getJSON,
])
postRequestWithAuth('/myRoute')({
uuid: 'ffda7b1c-fc6b-4949-98c4-e5cb86675f5f',
body: { hello: 'world' },
})
[pipe
与ramda的管道类似,因为它将函数链接在一起,但是对于异步函数,它将在将值传递给下一个函数之前解析返回的promise。
fork
是对象合成函数。在这种情况下,我们将为fork传递条目property: function
的对象。 fork的名称是因为它“分叉”或将输入数据并行化到条目的每个功能。最终输出是带有条目property: function(inputData)
的对象。
[get
就像ramda的prop