Javascript Promise.all位于带有FP的promises的对象数组上
因此,我使用NodeJS和Ramda,我有一个对象数组,如:Javascript Promise.all位于带有FP的promises的对象数组上,javascript,node.js,functional-programming,ramda.js,Javascript,Node.js,Functional Programming,Ramda.js,因此,我使用NodeJS和Ramda,我有一个对象数组,如: [ { x: 'abc', y: [] }, { x: '123', y: [1, 2, 3] } ] 然后我想在返回承诺的请求中使用x,结果是(使用over和lensProp来自Ramda): [ { x:我保证, y:[] }, { x:我保证, y:[1,2,3] } ] 现在我想将最后一个数组转换为: Promise<[
[
{
x: 'abc',
y: []
},
{
x: '123',
y: [1, 2, 3]
}
]
然后我想在返回承诺的请求中使用x
,结果是(使用over
和lensProp
来自Ramda):
[
{
x:我保证,
y:[]
},
{
x:我保证,
y:[1,2,3]
}
]
现在我想将最后一个数组转换为:
Promise<[
{
x: String,
y: []
},
{
x: String,
y: [1, 2, 3]
}
]>
承诺
我如何以函数式的方式实现这一点(比如在函数式编程中,而不是在一些只起作用的东西中=])
我能想到的最好办法是从
x
获得所有承诺,使用Promise.all
并使用然后到zip
将结果与y
s一起返回。但我不接受这一解决方案。一个选项是引入一个新的助手函数,其行为类似于R.traverse
,专门用于承诺,并将处理对象的特定属性。让我们称之为traversePropP
:
// traversePropP :: (a -> Promise b) -> String -> {a|...} -> Promise {b|...}
const traversePropP = R.curry((toPromiseFn, prop, obj) =>
toPromiseFn(obj[prop]).then(v => R.assoc(prop, v, obj)))
这可以有效地让您从对象的指定属性生成承诺,用创建的承诺解析的最终值替换该属性
然后,您可以使用此新函数映射数组中的所有对象,然后将生成的承诺数组传递给Promise.all
const traversePropP=R.curry((toPromiseFn,prop,obj)=>
toPromiseFn(obj[prop])。然后(v=>R.assoc(prop,v,obj)))
//延迟值的示例Promise生成函数
常数delayP=n=>x=>
新承诺((res,rej)=>setTimeout(()=>res(x,n))
常数fn=R.管道(
R.map(traversePropP(delayP(500),'x')),
x=>Promise.all(x)
)
常数数据=[
{
x:‘abc’,
y:[]
},
{
x:'123',
y:[1,2,3]
}
]
console.log('begin')
fn(data).then(x=>console.log('result:',x))
这里有一个干净的方法来做你想做的事
从'rubico'导入{pipe,assign,map,get}
const makeRequest=async x=>{/*…*/}
常数数据=[
{x:'abc',y:[]},
{x:'123',y:[1,2,3]},
]
地图(分配)({
x:pipe([get('x'),makeRequest]),
}))(数据)
最后的输出是一个对象数组的承诺,该数组的x
属性被请求的结果覆盖promise.all(array.map({x,y})=>x.then(x=>({x,y})))代码>
// traversePropP :: (a -> Promise b) -> String -> {a|...} -> Promise {b|...}
const traversePropP = R.curry((toPromiseFn, prop, obj) =>
toPromiseFn(obj[prop]).then(v => R.assoc(prop, v, obj)))