assemblyjs

1.1.0 • Public • Published

Assembly

NPM Version

警告

由於WebAssembly即將到來,為了防止誤會,我將停止更新Assembly,並將後續開發與維護轉移至Packhouse套件。

簡介

javascript是一個基於非同步驅動,且有數種呼叫function的概念,這點讓js於functional programming設計下險些困難。

而Assembly是一個函數包裝器,求助些許物件導向的概念,編寫出來的function可以泛用各種型態,並適應鍊式寫法。

安裝

npm

npm i assemblyjs

web

<script src="./dist/index.js"></script>
let factory = new Assembly()

webpack

import Assembly from 'assemblyjs'
let factory = new Assembly()

nodejs

let Assembly = require('assemblyjs')
let factory = new Assembly()

如何開始

建立工廠

Assembly是集結Group的工廠

Bridge是每次從工廠呼叫function時都會執行的函式,初始目的是為了動態載入group

let factory = new Assembly()
factory.setBridge((factory, groupName, toolName) => {
    if (factory.hasGroup(groupName) === false) {
        factory.addGroup(groupName, require(`./${groupName}`))
    }
})

Group

所有的function都必須在group下建構,因此建立group是第一步。

let group = new Assembly.Group()

當group被Assembly引入時可以藉由create客製化屬性,可用於模組化管理

alias只賦予系統訊息的命名,而非factory呼叫的key

let group = new Assembly.Group({
    alias: 'math',
    create(options) {
        this.options = options // {coefficient: 5}
    }
})
factory.addGroup('math', group, {
    coefficient: 5
})

Alone

獨立Group,使其不再受Factory管制。

let group = new Assembly.Group({
    create(options) {
        this.options = options // {coefficient: 5}
    }
})
group.addTool({
    name: 'sum',
    allowDirect: true,
    action: function(a, b, { include, group, store }, error, success) {
        success(+ b)
    }
})
let alone = group.alone({
    coefficient: 5
})
alone.tool('sum').direct(5, 10) // 15

Merger And Coop (ver1.0.8)

Merger是Group互相引用的接口

Merger的Group也會觸發create,請避免把負責被引用的Group加入Factory,除非他不需要接收外部參數

let valid = new Assembly.Group()
valid.addTool({
    name: 'validNumber',
    action: function(number, { include, group, store }, error, success) {
        if (typeof number === "number") {
            success()
        } else {
            error()
        }
    }
})
 
let math = new Assembly.Group({
    merger: { valid }
})
 
math.addTool({
    name: 'double',
    action: function(number, { include, group, store, coop }, error, success) {
        coop('valid').tool('validNumber').ng(error).action(number, () => {
            success(number * 2)
        })
    }
})

Tool

Tool是一個裝載function的單位,由group建造

Assembly帶有一個參數解析器,但在js不斷突變的狀況下,我無法保證該解析器能夠處理所有狀況,盡可能使用paramLength來處理,且定義paramLength將跳過執行解析器的動作,可以提供良好的效能

group.addTool({
    // (Require) function name
    name: 'sumAndAdd5',
    // 是否支援直接回傳,若有非同步處理請關閉(預設:true)
    allowDirect: true,
    // 手動定義參數長度
    paramLength: 2,
    // 在喚醒這個tool時建立
    create: function(store, { include, group }) {
        store.hello = 'world' // store是一個對外物件,你有需要的時候就會想到它的
        this.add = group.options.coefficient
    },
    // (Require) 對於外部來看這是個function(a,b),並沒有其他參數
    action: function(a, b, { include, group, store }, error, success) {
        success(+ b + this.add)
    }
})

呼叫function

let sumAndAdd5 = factory.tool('math', 'sumAndAdd5')
sumAndAdd5.store('hello') // 'world'
sumAndAdd5.direct(5, 10) // 20
sumAndAdd5.action(5, 10, (err, result) => {
    console.log(result) // 20
})
sumAndAdd5.promise(5, 10).then((result) => {
    console.log(result) // 20
})
 
// look for normal function.
let saa5 = sumAndAdd5.direct
saa5(5, 10) // 20

預填裝 (ver1.0.3)

let sumAndAdd5 = factory.tool('math', 'sumAndAdd5').packing(5, 10)
sumAndAdd5.direct() // 20
let sumAndAdd5 = factory.tool('math', 'sumAndAdd5').packing(5)
sumAndAdd5.direct(15) // 25
let sumAndAdd5 = factory.tool('math', 'sumAndAdd5').packing(5).packing(5)
sumAndAdd5.direct() // 15

解除預填裝 (ver1.0.6)

let sumAndAdd5 = factory.tool('math', 'sumAndAdd5').packing(5, 10).unPacking().direct(5, 5) // 15

預監聽錯誤 (ver1.0.5)

NG將協助你捕捉錯誤或優化程式碼

group.addTool({
    name: 'errorDemo',
    allowDirect: true,
    action: function(a, b, { include, group, store }, error, success) {
        let t = Math.random() > 0.5 ? error : success
        t()
    }
})
action

action預先呼叫錯誤,最後的callback將忽略賦予error

factory.tool('math', 'errorDemo').ng((err)=>{
    console.log(err)
}).action((res) => {
    console.log(res)
})
direct

direct原本在錯誤處裡上會直接throw error,但預處理則呼叫callback

factory.tool('math', 'errorDemo').ng((err)=>{
    console.log(err)
}).direct()
promise

promise在遭遇錯誤仍然會宣告reject,但同時執行錯誤的回呼函式

factory.tool('math', 'errorDemo').ng((err)=>{
    console.log(err)
}).promise()

Mold (v1.1.0)

Mold是一個參數配裝器,只支援同步處理,用於參數驗證與型態轉換。

group.addMold({
    // (Require) mold name
    name: 'int',
    // 回傳非true及驗證錯誤與回傳訊息
    check(param) {
        return typeof param === 'number' ? true : 'Not a number.'
    },
    // 參數處理
    casting(param) {
        return Number.floor(param)
    }
})
group.addTool({
    name: 'multiply',
    mold: [null, 'int'], //設定b參數一定要整數
    action: function(a, b, system, error, success) {
        success(* b)
    }
})
 
factory.tool('math', 'multiply').direct(5.5, 10) // 55
factory.tool('math', 'multiply').direct(10, 5.5) // 50
factory.tool('math', 'multiply').direct(10, '5.5') // error 'Not a number.'

生產線

建構生產線是一個函數柯理化(curry)的過程,在這之前,先將整個function給定義好

include是一個Tool互相溝通的接口,作用域只到當下的group

let math = new Assembly.Group()
math.addTool({
    name: 'isNumber',
    allowDirect: false,
    action: function(params, { include }, error, success) {
     let values = params.filter((n) => {
            return typeof n !== 'number'
        })
        if (values.length === 0) {
            success(true)
        } else {
            error('no number')
        }
    }
})
math.addTool({
    name: 'sum',
    allowDirect: true,
    action: function(a, b, { include }, error, success) {
        include('isNumber').action([a, b], (err) => {
            if (err == null) {
             success(+ b)
            } else {
                error(err)
            }
        })
    }
})
math.addTool({
    name: 'double',
    allowDirect: true,
    action: function(number, { include }, error, success) {
        include('isNumber').action([number], (err) => {
            if (err == null) {
                success(number * 2)
            } else {
                error(err)
            }
        })
    }
})
 
factory.addGroup('math', math)

建構生產線

和Tool一樣,生產線仍依附在group上

group.addLine({
    name: 'compute',
    // 初始化是難免的,inlet會限制第一個呼叫的function,當其為null或空陣列時不限制
    inlet: ['add'],
    // 每次執行line都會刷新this的屬性
    input: function(number, { include }, error, start) {
     this.number = number
        start()
    },
    output: function({ include }, error, success) {
     success(this.number)
    },
    // 當執行鍊中觸發error就會觸發fail,err:{ stack, message} 的物件
    fail: function(err, report) {
     report(err)
    },
    // layout為一個鍊中能呼叫的函數表,實質為Tool個體
    layout: {
        add: function(number, { include }, error, next) {
            include('sum').action(this.number, number, (err, result) => {
                if (err) {
                    error(err)
                } else {
                    this.number = result
                    next()
                }
            })
        },
     double: function({ include }, error, next) {
            include('double').action(this.number, (err, result) => {
                if (err) {
                    error(err)
                } else {
                    this.number = result
                    next()
                }
            })
        }
    }
})

執行生產線

將5丟進去input之後,經由生產線擲出result

line不支援direct

factory.line('math', 'compute')(5).add(10).double().double().action((err, result) => {
    console.log(result) // 60
})
factory.line('math', 'compute')(5).add(10).double().promise().then((result) => {
    console.log(result) // 30
})

其他

版本LOG

開發者文件

Package Sidebar

Install

npm i assemblyjs

Weekly Downloads

0

Version

1.1.0

License

ISC

Unpacked Size

108 kB

Total Files

15

Last publish

Collaborators

  • khczhihao