【问题标题】:Promise.all on array of objects with promises with FPPromise.all 在带有 FP 承诺的对象数组上
【发布时间】:2019-01-05 04:39:36
【问题描述】:

所以,我正在使用 NodeJS 和 Ramda,并且我有一个对象数组,例如:

[
    {
        x: 'abc',
        y: []
    },
    {
        x: '123',
        y: [1, 2, 3]
    }
]

然后我想在返回承诺的请求中使用x,从而导致这个(使用来自 Ramda 的 overlensProp):

[
    {
        x: Promise<String>,
        y: []
    },
    {
        x: Promise<String>,
        y: [1, 2, 3]
    }
]

现在我想把最后一个数组变成这样:

Promise<[
    {
        x: String,
        y: []
    },
    {
        x: String,
        y: [1, 2, 3]
    }
]>

我怎样才能以函数式的方式实现这一点(如在函数式编程中,而不是像在正常工作的东西中 =])?

我能想到的最好的办法是从x 获得所有承诺,使用Promise.all 并使用thenzip,结果返回ys。但我不接受将其作为解决方案。

【问题讨论】:

  • Promise.all(array.map(({x,y})=&gt;x.then(x=&gt;({x,y}))));

标签: javascript node.js functional-programming ramda.js


【解决方案1】:

这是一种干净的方式来做你想做的事。

import { pipe, assign, map, get } from 'rubico'

const makeRequest = async x => {/* ... */}

const data = [
  { x: 'abc', y: [] },
  { x: '123', y: [1, 2, 3] },
]

map(assign({
  x: pipe([get('x'), makeRequest]),
}))(data)

最终输出是一个对象数组的承诺,其中 x 属性被请求的结果覆盖

【讨论】:

    【解决方案2】:

    一种选择是引入一个新的辅助函数,它的行为类似于R.traverse,它专门用于 Promises,并将作用于对象的特定属性。让我们称之为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,将属性替换为由创建的 Promise 解析的最终值。

    然后您可以使用这个新函数来映射数组中的所有对象,然后将生成的 Promises 数组传递给Promise.all

    const traversePropP = R.curry((toPromiseFn, prop, obj) =>
      toPromiseFn(obj[prop]).then(v => R.assoc(prop, v, obj)))
    
    // example Promise-producing function that delays a value
    const delayP = n => x =>
      new Promise((res, rej) => setTimeout(() => res(x), n))
    
    const fn = R.pipe(
      R.map(traversePropP(delayP(500), 'x')),
      x => Promise.all(x)
    )
    
    const data = [
        {
            x: 'abc',
            y: []
        },
        {
            x: '123',
            y: [1, 2, 3]
        }
    ]
    
    console.log('begin')
    fn(data).then(x => console.log('result:', x))
    &lt;script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"&gt;&lt;/script&gt;

    【讨论】:

      猜你喜欢
      • 2017-05-17
      • 2020-04-24
      • 2016-11-25
      • 2017-12-14
      • 2017-04-05
      • 1970-01-01
      • 1970-01-01
      • 2022-08-20
      相关资源
      最近更新 更多