重磅升级千峰2023java就业班-日出江花红胜火
JS 函数式概念: 管道 和 组合
重磅升级千峰2023java就业班
download:https://www.51xuebc.com/thread-530-1-1.html
函数管道和组合是函数式编程中的概念,当然也能够在JavaScript中完成--由于它是一种多范式的编程言语,让我们快速深化理解这个概念。
这个概念就是依照一定的次第执行多个函数,并将一个函数的结果传送给下一个函数。
你能够像这样做得很难看:
function1(function2(function3(initialArg)))
或者运用函数组合:
compose(function3, function2, function1)(initialArg);
或功用管道:
pipe(function1, function2, function3)(initialArg);
简而言之,组合和管道简直是一样的,独一的区别是执行次第;假如函数从左到右执行,就是管道,另一方面,假如函数从右到左执行,就叫组合。
一个更精确的定义是。"在函数式编程中,compose是将较小的单元(我们的函数)组合成更复杂的东西(你猜对了,是另一个函数)的机制"。
下面是一个管道函数的例子。
const pipe = (...functions) => (value) => {
return functions.reduce((currentValue, currentFunction) => {
return currentFunction(currentValue);
}, value);
};
让我们来补充一些这方面的见解。
根底学问
我们需求搜集N多的函数
同时选择一个参数
以链式方式执行它们,将收到的参数传送给将被执行的第一个函数
调用下一个函数,参加第一个函数的结果作为参数。
继续对数组中的每个函数做同样的操作。
/* destructuring to unpack our array of functions into functions */
const pipe = (...functions) =>
/* value is the received argument */
(value) => {
/* reduce helps by doing the iteration over all functions stacking the result */
return functions.reduce((currentValue, currentFunction) => {
/* we return the current function, sending the current value to it */
return currentFunction(currentValue);
}, value);
};
我们曾经晓得,箭头函数假如只返回一条语句,就不需求括号,也不需求返回标签,所以我们能够经过这样写来减少键盘的点击次数。
const pipe = (...functions) => (input) => functions.reduce((chain, func) => func(chain), input);
如何运用
const pipe = (...fns) => (input) => fns.reduce((chain, func) => func(chain), input);
const sum = (...args) => args.flat(1).reduce((x, y) => x + y);
const square = (val) => val*val;
pipe(sum, square)([3, 5]); // 64
记住,第一个函数是左边的那个(Pipe),所以3+5=8,8的平方是64。我们的测试很顺利,一切似乎都很正常,但假如要用链式 async 函数呢?
异步函数上的管道
我在这方面的一个用例是有一个中间件来处置客户端和网关之间的恳求,过程总是相同的(做恳求,错误处置,选择响应中的数据,处置响应以烹制一些数据,等等等等),所以让它看起来像一个魅力。
export default async function handler(req, res) {
switch (req.method) {
case 'GET':
return pipeAsync(provide, parseData, answer)(req.headers);
/*
...
*/
让我们看看如何在Javascript和Typescript中处置异步函数管道。
JS版
export const pipeAsync =
(...fns) =>
(input) =>
fns.reduce((chain, func) => chain.then(func), Promise.resolve(input));
添加了JSDoc类型,使其更容易了解(我猜)。
/**
* Applies Function piping to an array of async Functions.
* @param {Promise<Function>[]} fns
* @returns {Function}
*/
export const pipeAsync =
(...fns) =>
(/** @type {any} */ input) =>
fns.reduce((/** @type {Promise<Function>} */ chain, /** @type {Function | Promise<Function> | any} */ func) => chain.then(func), Promise.resolve(input));
TS版
export const pipeAsync: any =
(...fns: Promise<Function>[]) =>
(input: any) =>
fns.reduce((chain: Promise<Function>, func: Function | Promise<Function> | any) => chain.then(func), Promise.resolve(input));
这样一来,它对异步和非异步函数都有效,所以它比上面的例子更胜一筹。
你可能想晓得函数的组成是什么,所以让我们来看看。
函数组合
假如你喜欢从右到左调用这些函数,你只需求将reduce改为redureRight,就能够了。让我们看看用函数组成的异步方式。
export const composeAsync =
(...fns) =>
(input) =>
fns.reduceRight((chain, func) => chain.then(func), Promise.resolve(input));
回到上面的例子,让我们复制同样的内容,但要有构图。
如何运用
const compose = (...fns) => (input) => fns.reduceRight((chain, func) => func(chain), input);
const sum = (...args) => args.flat(1).reduce((x, y) => x + y);
const square = (val) => val*val;
compose(square, sum)([3, 5]); // 64
请留意,我们颠倒了函数的次第,以坚持与帖子顶部的例子分歧。
如今,sum(位于最右边的位置)将被首先调用,因而3+5=8,然后8的平方是64。