首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Currying/ Piping函数

使用Currying/ Piping函数
EN

Stack Overflow用户
提问于 2018-10-10 11:53:32
回答 2查看 423关注 0票数 0

我目前正在使用Ramda library来构造新函数。下面是我的代码片段

代码语言:javascript
复制
function auth(operand) {
  if (operand.prevResult.pass && operand.req.authenticated) {
    return operand;
  } else {
    operand.prevResult.pass = false;
    return operand;
  }
}

function validate(operand) {
  if (operand.prevResult.pass && operand.req.validated) {
    return operand;
  } else {
    operand.prevResult.pass = false;
    return operand;
  }
}

function postHandle(operand) {
  if (operand.prevResult.pass){
    operand.res.send();
  } else {
    console.log('some error occured')
  }

}

const doPost = R.pipe(auth, validate, postHandle);
//const doGet = R.pipe(auth, validate, getHandle);
//const doPatch ...etc

const req = {authenticated: true, validated: true};
const res = {send: () => {console.log('sent')}};
doPost({req, res, prevResult: {pass: true}});

目标是能够使用一些共享方法创建doPostdoGetdoPatch etcs,比如身份验证/验证。

然而,我能找到的最好的函数是Ramda中的R.pipe。这样做是这样的

(((a, b, …, n) → o), (o → p), …, (x → y), (y → z)) → ((a, b, …, n) → z)

它只允许我在构造的函数中传入一个参数(例如,doPost,doGet)。因此,最后一行doPost({req, res, prevResult: {pass: true}});

我希望有一种方法可以让我传入三个参数。所以我可以在最后做doPost(req, res, {pass: true})。而且每个函数的签名也会看起来更好,就像function auth(req, res, prevResult)function validate(req, res, prevResult)function postHandle(req, res, prevResult)

EN

回答 2

Stack Overflow用户

发布于 2018-10-10 17:40:49

R.pipe:除第一个函数外,所有函数都将只接受一个参数。

我们可以通过使用curry函数R.curry来克服这个问题。

通常,curry函数会返回一个函数,直到它获得了函数签名中提到的所有参数。

创建auth、validate和postHandle的curried版本,如下所述。我希望这能解决你的问题。

代码语言:javascript
复制
const R = require('ramda');

const isPrevResultPass = R.propEq('pass', true);
const isAuthenticated = R.propEq('authenticated', true);
const isValidated = R.propEq('validated', true);
const updatePrevResultPass = R.assoc('pass');

const auth = R.curry((req, res, prevResult) => {
    if (isPrevResultPass(prevResult) && isAuthenticated(req))
        return prevResult;
    return updatePrevResultPass(false, prevResult)
});

const validate = R.curry((req, res, prevResult) => {
    if (isPrevResultPass(prevResult) && isValidated(req))
        return prevResult;
    return updatePrevResultPass(false, prevResult);
});

const postHandle = R.curry((req, res, prevResult) => {
    if (R.not(isPrevResultPass(prevResult)))
        console.log('some error occured')
    res.send();
});


const req = {authenticated: true, validated: true};
const res = {send: () => {console.log('sent')}};
const prevResult = { pass: true };

const doPost = R.pipe(auth(req, res), validate(req, res), postHandle(req, res));
doPost(prevResult);
票数 0
EN

Stack Overflow用户

发布于 2018-10-10 18:52:22

如果希望通过函数组合传递多个值,则需要能够从各个函数返回多个值。

要做到这一点,一种方法是使用一个像你这样的对象(尽管响应Shyam的注释来改变参数的结构,以帮助提高可读性)。

在一系列组合函数中的函数之间传输多个值的另一种方法是通过延续传递样式,其中所提供的回调期望接收多个结果。

代码语言:javascript
复制
const multiPipe = (...fns) => fns.reduceRight(
    (pipe, next) => (...args) => next(...args)(pipe))

const fn = multiPipe(
  (a, b) => k => k(a * 2, b * 3),
  (a, b) => k => k(a - 5, b - 2)
)

fn(1, 2)((a, b) => console.log(a, b))

从continuation传递方式中获得的一个有趣功能是,您还可以缩短管道,以防止通过返回结果而不调用所提供的continuation来调用剩余的函数。

代码语言:javascript
复制
const multiPipe = (...fns) => fns.reduceRight(
    (pipe, next) => (...args) => next(...args)(pipe))

const auth = (req, res) => next =>
  req.authenticated
    ? next(req, res)
    : console.log('authentication failed')

const validate = (req, res) => next =>
  req.validated
    ? next(req, res)
    : console.log('validation failed')

const postHandle = (req, res) => next =>
  res.send()

const doPost = (req, res) =>
  multiPipe(auth, validate, postHandle)(req, res)()

const req = { authenticated: true, validated: true }
const res = { send: () => console.log('sent') }

doPost(req, res)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52732373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档