我遇到的情况是,我想要添加的值取决于 future 的值,即
let metadata = {videoId: 123, likes: 400};
let addSubtitles = R.assoc('subtitles', R.__, R.__);
这里addSubtitles
是一个部分应用的函数。然而,addSubtitles 的第二个参数应该是字幕,但字幕本身依赖于第三个参数,即metadata.videoId。调用方式如下:
addSubtitles(metadata); //but with another argument perhaps?
const subtitles = async getSubtitles(videoId) => await apiCall(videoId);
有什么办法可以以功能性的方式解决这个问题吗?如果我要限制 future 第三个参数的上下文,似乎是可能的,但不确定如何去做。
如果需要回答任何额外信息,请告诉我。
这是一个可行的解决方案,尽管我希望使用 Ramda 来实现此目的:
const addSubs = async function(el) {¬
const subtitles = await writeCaptions(el.videoId);¬
return R.assoc('subtitles', subtitles, el);¬
};
最佳答案
首先让我回顾一下,您不需要使用 R._
来获取签名中的后续值。 Ramda 库中的几乎每个函数都会为您自动柯里化(Currying),因此您可以使用所有参数或仅使用某些子集来调用来预加载数据。 R._
仅用于为将来的调用保留空间。
因此,您想要对柯里化(Currying)执行的操作就是不断地一次添加一个参数,直到您准备好调用一个完整的函数为止。当顺序错误时,您可以使用 R.flip
或 R._
(取决于上下文)到达您准备填充的值,然后返回到这些值你还不知道。
因此,从您的描述来看,您担心的似乎是 getSubtitles(metadata)
是一个返回 promise 的网络调用。本示例将在该假设下进行。在这里,我认为 R.flip
对您来说比 R._
更具表现力。
const metadata = { videoId: 123, likes: 400 }
const addSubtitles = R.flip(R.assoc('subtitles'))
// Now you have a curried function that takes 2 arguments, first the metadata, and then the subtitles.
const withSubtitlesPromise = getSubtitles(metadata)
// Here we drill down a little further by adding the metadata, and then
// pass it as the callback to .then, which will pass in the final param
// once it resolves
.then(addSubtitles(metadata)
withSubtitlesPromise.then(console.log)
您绝对可以在一个函数中捕获所有这些逻辑,该函数接受元数据
并返回字幕数据的 promise 。为了更好地衡量,我们还将传入 getSubtitles
作为依赖项,以便更容易测试和弱耦合。现在,更换另一个用于检索字幕数据的函数就很简单了。在本例中,使用 R._
使代码更加简洁,因此我们将对其进行切换。
// Define all the logic in a single easy function
const makeAddSubtitles = getSubtitles => metadata =>
getSubtitles(metadata).then(R.assoc('subtitles', R._, metadata))
// Then push in the dependency
const addSubtitles = makeAddSubtitles(getSubtitles)
// Use it
const vid123 = { videoId: 123, likes: 400 }
const vid123WithSubsPromise = addSubtitles(vid123)
关于javascript - Ramda - 部分应用的功能取决于完整的应用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48574888/