npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@szmg-fe/funba

v0.0.42

Published

function library

Downloads

3

Readme

Funba

函数式编程总是令人愉悦,面向函数,相信你会快乐起来(Fun)吧(ba) -- Funba

Funba基于ramda、data.task、lodash的函数式编程应用库,核心围绕Task,通过curry&compose提供point free的代码风格,同时提供一些utils函数,Funba已通过jest覆盖单元测试

你可能需要熟悉

Usage

data.task的用例非常少,官方只展示了chain的用法,这里会先展示其他的函子接口如何使用

ap

将Task中的function apply于另一个task中的value

import ap from 'funba/ap';
import Task from 'funba/task';
import {compose} from 'funba/ramda'
import fork from 'funba/fork'
import {log, error} from 'funba/console'

const add = new Task(function (reject, resolve) {
    setTimeout(function () {
        resolve(function (x) {
            return x + 1;
        });
    }, 1000);
});

const  multiply = new Task(function (reject, resolve) {
    setTimeout(function () {
        resolve(function (x) {
            return x * 10;
        });
    }, 5000);
});

const value = new Task(function (reject, resolve) {
    setTimeout(function () {
        resolve(1);
    }, 1000);
});

const calculateValue = compose(fork(error, log), ap(value));

calculateValue(add); // 2
calculateValue(multiply); // 10

all

ap的高阶应用 - 并发处理相当于Promise.all

import createAction from 'funba/actionCreater';
import {compose} from 'funba/ramda'
import {error, log} from 'funba/console'
import all from 'funba/all';

const action = createAction(error);
const createTaskByNumber = n => new Task((rej, res) => {
    setTimeout(() => res(n), n * 1000);
});
const [http1, http3, http5] = [1, 3, 5].map(n => createTaskByNumber(n));

const http135 = compose(action(log), all([http1, http3, http5]);
http135((x, y, z) => x + y + z); // 9

race

concat的高阶应用,处理并发竟态

const action = createAction(log);

const createTaskByNumber = n => new Task((rej, res) => {
    setTimeout(() => res(n), n * 1000);
});

const [http1, http3, http5] = [1, 3, 5].map(n => createTaskByNumber(n));
compose(action(log), race)([http1, http3, http5]); // log 1

bimap

分别处理一个函子中的reject和resolve

import Task from 'funba/Task';
import { compose } from 'funba/ramda';
import bimap from 'funba/bimap';
import fork from 'funba/fork';
import {error, log} from 'funba/console'

const cfTask = n => new Task((rej, res) => {

    if (n >= 5) {
        res(n)
    } else {
        rej(n)
    }
});

compose(fork(error, log), bimap(x => x + 1, x => x - 1), cfTask)(5); // log - 4
compose(fork(error, log), bimap(x => x + 1, x => x - 1), cfTask)(2); // error - 3

chain

串联执行task

const cfTask = n => new Task((rej, res) => {
    res(n);
});

const add = x => new Task((rej, res) => {
    res(x + 5);
});

const mutiply = x => new Task((rej, res) => {
    res(x * 5);
});

compose(fork(error, log),chain(mutiply), chain(add), cfTask)(5); // 50

fold

分别作用于函子的reject和resolve,并在外部的resolve获取

bimap的不同点在于 bimap可以在reject中获取f作用的value

const cfTask = n => new Task((rej, res) => {

    if (n >= 5) {
        res(n)
    } else {
        rej(n)
    }
});

compose(fork(error, log), fold(x => x + 1, x => x - 1), cfTask)(5); // log 4
compose(fork(error, log), fold(x => x + 1, x => x - 1), cfTask)(2); // log 3

fork

Task的执行api

import fork from 'funba/fork';
import Task from 'funba/Task';
import {error} from 'funba/console';

new Task((rej) => rej(1)).fork(error); // error 1;

id

将参数直接返回

import id from 'funba/id';

id(2) === 2;
id(true) === true

of

Task生成器

import of from 'funba/of'
of(1) === new Task((rej, res) => res(1));

rejectedMap

rejectedMap反向的map

new Task((rej) => rej(1)).rejectedMap(x => x + 5).fork(error); // error 6

orElse

反向的chain,作用在task的reject

const cfTask = n => new Task((rej, res) => {

    if (n >= 5) {
        res(n)
    } else {
        rej(n)
    }
});

const add = n => new Task((rej, res) => {
    rej(n + 5);
})

const multiply = n => new Task((rej, res) => {
    rej(n * 5);
})

const multiply2 = n => new Task((rej, res) => {
    res(n * 8);
})

compose(fork(error), orElse(multiply), orElse(add), cfTask)(1); // error 30

createAction

快速生成一个action - 封装fork(f, g)行为

import createAction from 'funba/createAction';
import {compose} from 'funba/ramda'
import {error, log} from 'funba/console'

const action = createAction(error);
const throwErr = n => new task((rej) => rej(n));
const run = compose(action(log), throwErr);
run(5); // error 5

createApi

api生成器

import api from 'funba/createApi';
import axiosHttp from 'funba/axiosHttp';

const axiosApi = api(axiosHttp);
const mockData = {'/api/login': {name: 'lemon'}};
const baiduApi = axiosApi('https://www.baidu.com' , mockData);

// 开启mock之后GetHttp&PostHttp都会返回mock数据
// Mock始终返回mock数据
const {
    GetHttp,
    PostHttp,
    Mock
} = baiduApi(true); 

// 同一个项目有非常多的api host的话
const baiduApi = axiosApi('https://www.baidu.com' , mockData);
const wxApi = axiosApi('https://www.wx.com' , mockData);
const alibabaApi = axiosApi('https://www.alibaba.com' , mockData);

bringFunction

类似于curry 将一个函数携带值去应用

import bringFunction from "funba/bringFunction";
const add = x => x + 1;
const _add = bringFunction(add);
const _add1 = _add(1);
_add1(); // 2

applyFunction

将参数传入一组函数使用,参数依次进行传递

import applyFunction from 'funba/applyFunction'
const data = {
    count: 0
};
const add1 = data => data.count+=1;
const add3 = data => data.count+=3;
const add5 = data => data.count+=5;
const app = applyFunction([add1, add3, add5]);

app(data); // data.count === 9

axiosApi

提供一个封装了axios的api

import axiosApi from 'funba/axiosApi'
const baiduApi = axiosApi('https://www.baidu.com', {});
const {
     GetHttp,
    PostHttp,
    Mock
} = baiduApi(true); // 开启mock

axiosHttp

提供了一个封装了axios的task,也可以直接使用axiosApi

import axiosHttp from 'funba/axiosHttp';
import fork from 'funba/fork';
import {log, error} from 'funba/console';

const sayHi = compose(fork(error, log), axiosHttp);
sayHi('www.baidu.com', 'get', '/api/sayHi', 'lemon');

backArgs

运行一个函数,但是返回参数

import backArgs from 'funba/backArgs';

const a = {
    count: 1
};
const b = {
    count: 2
}
const add = backArgs(x => b.count = b.count + x.count);
add(a) === a // true

checkSpace

检查空字符

import checkSpace from 'funba/checkSpace';
checkSpace('') // true

createParamsString

将一个对象转换成query string

import createParamsString from 'funba/createParamsString';

createParamsString({a: 1, b: 2}) === '?a=1&b=2';

date

提供轻量级的时间格式化工具

import {dateFormat_yy_mm_dd} from 'funba/date';
dateFormat_yy_mm_dd(Date.now()); // 2021-12-01;

invertBoolean

转换成反布尔值

import invertBoolean from 'funba/invertBoolean';
invertBoolean(1) === false

mock

接收一个mockdata对象 返回一个mock请求Task

// createApi源码部分
const mockHttpApi = mock(mockData);  // 直接返回一个mock
const curryMockHttpApi = curry(mockHttpApi);
const getMockHttp = curryMockHttpApi(server, 'GET');
const Mock = (url: string) => compose(getMockHttp(url), id); // mock请求

createMockData

收集mockData

const loginMock = {
    '/api/login': {name: 'lemon'}
}

const articleMock = {
    '/api/getList': []
};

const mockData = createMockData(); // createMockData可以接收一个格式化函数
const allMockData = mockData(
    loginMock,
    articleMock
);

packPromise

接收一个Promise,让这个promise始终有返回值

const a = async () => packPromise(new Promise((res, rej) => {

    setTimeout(() => res(5), 2000);
}));
const [res, err] = await a(); // res 5 , err undefined

prop

获取属性

import prop from 'funba/prop';
prop('key', {key: 1}); // 1

compose

函数组合, 来自ramda

import {compose} from 'funba/ramda'

curry

函数柯里化, 来自ramda

import {curry} from 'funba/ramda'

map

map方法,既可以处理函子也可以处理数组, 来自ramda

import {map} from 'funba/ramda'

concat

concat, 来自ramda

import {concat} from 'funba/ramda'

head

head,取出数组第一项, 来自ramda

import {head} from 'funba/ramda'

selectNum

一定范围内的随机数

import selectNum from 'funba/selectNum';
selectNum(0, 10); // 5

replace

柯里化字符串替换

import replace from 'funba/replace';
const replaceSpace = replace(regSpace, '');
replaceSpace('12 43 45'); // 124345

requestLog

log请求日志

trace

compose中的断点工具

compose(log, trace('after error'), error)

localStorage

操作localStorage

const saveStorage = setLocalStorage('user');
saveStorage({name: 'lemon'});

getLocalStorage('user'); => {name: 'lemon'}

isWx

判断是否为微信内

Test

yarn test
yarn report

report

markdown