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

process-table

v0.0.7

Published

JavaScript 流程管理机制

Downloads

13

Readme

process

基于单向数据流的 JavaScript 流程管理机制

工作原理

在 JavaScript 中,变量所对应的值,可以在函数之间传入与返回。

var add = function(num) {
    return num + 1
}
var minus = function(num) {
    return num - 1
}

minus(add(add(1))) // => 2

对于异步的场景,我们也拥有 es6.promise 可以传递返回值。

var add = function(num) {
    return num + 1
}
var minus = function(num) {
    return num - 1
}
Promise.resolve(1).then(add).then(add).then(minus).then(function(value) {
    console.log(value) // => 2
})

我们完全可以将上述两种技术整合到一起,像下面这样运用:

var add = function(num) {
    return num + 1
}
var minus = function(num) {
    return num - 1
}
var asyncAdd = function(num) {
    return new Promise(function(resolve) {
        setTimeout(resolve.bind(null, num + 1), 200)
    })
}
var taskStore = {
    add4: [add, add, add, add, minus, add] //调用5次add,一次minus,使一个数值增加4
    asyncAdd3: [add, minus, asyncAdd, add, asyncAdd] //异步增值场景
}
//设想有这种 API
var process = new Process(taskStore)

//像这样传入初始值

//同步场景
process.resolve('add4', -4) // => 0

//异步场景
process.resolve('asyncAdd3', -3).then(function(value) {
    console.log(value) // => 0
})

这样做有几个好处:

  • 数据传递方式更为整洁和直观。像这种 minus(add(add(1))) 代码从阅读顺序上,是反直觉的,最先出现的 minus 实际上最后调用

  • 模糊化同步与异步的差别。asyncAdd 后面的 add 不需要显示地写 then 函数

  • 增强可维护性。修改某个处理环节,能够快速而又明确对应到具体函数;增加某个环节、调整某几个环节的顺序,也非常便利。

就上面显示的情形来说,还有几个问题有待解决。

如何复用一个函数组合?

当 taskHandler 是字符串类型时,跳转到其对应的 taskStore[taskHandler]

var taskStore = {
    add4: [add, add, add, add, minus, add] //调用5次add,一次minus,使一个数值增加4
    asyncAdd3: [add, minus, asyncAdd, add, asyncAdd] //异步增值场景
    asyncAdd7: ['add4', 'asyncAdd3'] //复用 add4 和 asyncAdd3
}

var process = new Process(taskStore)

//异步场景
process.resolve('asyncAdd7', -7).then(function(value) {
    console.log(value) // => 0
})

如何中断传值?

在 js 中有两个表示空的数据类型,一个是 undefined ,另一个是 null。前者是函数默认返回值,所以我们可以用后者来作为中断传值的标识。

当一个 taskHandler 返回 null 时,后面的 taskHandler 将不会执行。

var process = new Process({
    add: [function(num) {
        return null
    }, function(num) {
        return num + 1
    }]
})

//中断传值都返回 null, 如果是异步的,那么 promise.resolve 的值也是 null
process.resolve('add', -1) // => null

如何便捷地记录状态?

Process 配置 state 属性,所有 taskHandler 接受三个参数: valuestateprocess

var taskStore = {
    update: function(value, state, process) {
        state.cache = value
        process.state === state // true
    }
}
var process = new Process(taskStore, {
    cache: '默认状态'
})

process.resolve('update', '更新状态')
process.state.cache // 更新状态

如何灵活跳转?

加入 taskHandler 是一个具有 goTo 方法的对象,那么将valuestateprocess传入其 goTo 方法,该方法返回一个新的 taskHandler,如果这个新的 taskHandler 是函数,则直接执行;是字符串,则跳转;是数组,则循环;还是 goTo 对象,则递归。

如果找不到合法的 taskHandler ,则跳过。

var add = function(num) {
    return num + 1
}
var minus = function(num) {
    return num - 1
}


var process = new Process({
    addToTen: [add, {
        goTo: function(value, state, process) {
            return value < 10 ? 'add' : null
        }
    }]
})

process.resolve('addToTen', -10) // => 10

如何做错误处理?

taskStore 中设置一个特殊属性 taskStore.error,它的规则与 taskStore 完全一样,只是调用规则不同。


//寻找 process.store.taskName ,调用它对应的 taskHandler 队列
process.resolve(taskName, value)

//寻找 process.store.error.errorName,调用它对应的 taskHandler 队列
process.reject(errorName, value)

如何嵌套传值?

process.willResolve(taskName)方法接受一个参数 taskName,返回一个接受 value 的函数,相当于 process.resolve.bind(process, taskName)

利用这个特性,两个 process 可以嵌套传值。

process1.extend({
    add: [add, add, process2.willResolve('add3'), process3.willReject('errorName01')]
})

安装方式

npm install process-table
  • CommonJs
var Process = require('process-table')
var add = function(num) {
    return num + 1
}
var process = new Process({
    add4: [add, add, add, add]
})

process.resolve('add4', 0) // => 4
  • AMD
define(['process'], function(Process) {
    var add = function(num) {
        return num + 1
    }
    var process = new Process({
        add4: [add, add, add, add]
    })
    
    process.resolve('add4', 0) // => 4
})
  • script
<script src="process.js"></script>
<sciprt>
var process = new Process({
    add: function(num) {
        return num + 1
    }
})
process.resolve('add', 9) // => 10
<script>

API 介绍

实例化 new Process(taskStore, initialState)

taskStore 是一个 key-value 对象,其 key 为 taskName,其 value 为 taskHandler。

taskHandler 可以是函数、字符串、数组、thanable 对象以及具有 goTo 方法的普通对象。

var taskStore = {
    showState: function(value, state, process) {
        console.log(state)
        return value
    },
    add: function(num, state) {
        return num + 1
    },
    minus: function(num) {
        return num - 1
    },
    add0: ['add', 'minus'] //task 允许数组、字符串、对象
    addToTen: {
        goTo: function(value) {
            return value < 10 ? 'add' : null
        }
    },
    error: {
        404: function(value) {
            console.log(value, 404)
        }
    }
}
var process = new Process(taskStore, {
    test: 'initial state'
})

process.resolve('minus', 10) // => 9
process.reject('404', 'test') // test 404 

Process#extend(...sources)

将 sources 合并到 process.store 属性中,返回 store

Process#resolve(taskName, value)

让 value 值在 taskName 所对应的 taskHandler 队列中传递,如果 taskHandler 全部是同步的,则返回最终的值。如果 taskHandler 队列中存在异步处理器,则返回 promise 对象。

Process#reject(errorName, value)

让 value 值在 errorName 对应的 errorHandler 队列中传递,返回值同 Process#resolve 方法。

Process#willResolve(taskName)

Process#resolve 的科里化函数,返回接受 value 参数的函数。

Process#willReject(errorName)

Process#reject 的科里化函数,返回接受 value 参数的函数。