RamdaJS - 如何使用具有同步和异步功能的管道?

RamdaJS - How can I use pipe with sync and async functions?

我正在尝试学习 Ramda 以及如何在日常工作中使用它。所以我有一个快速的问题。 "How can I use pipe with sync and async functions?" 或者最好,我怎样才能改进下面的代码?

const AuthService = () => ({
  async signIn(credentials: Credentials): Promise<AuthSession> {
    const result = await api.signIn(credentials)

    return R.pipe(
      signInResultToAuthSession,
      saveAuthSession
    )(result)
  }
})

[编辑]:我认为更好的第二种选择。

const AuthService = () => ({
  async signIn(credentials: Credentials): Promise<AuthSession> {
    return api.signIn(credentials).then(
      R.pipe(
        signInResultToAuthSession,
        saveAuthSession
      )
    )
  }
})

您可以创建这样的函数:

const then = f => p => p.then(f)

然后你的管道看起来像:

const AuthService = () => ({
  async signIn(credentials: Credentials): Promise<AuthSession> {
    return R.pipe(
      api.signIn,
      then(signInResultToAuthSession),
      then(saveAuthSession),
    )(credentials)
  }
})

您甚至可以通过以下方式捕获异常:

const pCatch = f => p => p.catch(f)
R.pipe(
   api.signIn,
   pCatch(err => console.error(err)),
   then(signInResultToAuthSession),
   then(saveAuthSession),
)(credentials)

pipeWith 就是为这种情况添加的。它将函数包装在一个公共接口中(此处 then)并传递结果,就像 pipe.

const api = {signIn: ({pwd, ...creds}) => Promise.resolve({...creds, signedIn: true})}
const signInResultToAuthSession = (creds) => Promise.resolve({...creds, auth: true})
const saveAuthSession = (creds) => Promise.resolve({...creds, saved: true})

const AuthService = {
  signIn: pipeWith(then)([
    api.signIn, // [1]
    signInResultToAuthSession,
    saveAuthSession
  ])
}

AuthService.signIn({name: 'fred', pwd: 'flintstone'})
  .then(console.log)

// [1]: `bind` might be necessary here, depending on the design of `api.signIn`
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>const {pipeWith, then} = R                                   </script>

请注意 pipeWith 将函数包装在一个数组中。有一天我们想对 pipe 做同样的事情,但这是一个巨大的突破性变化。