Brook JavaScript框架核心概念与MVC实现详解

作者:小括号

时间:2026-10-26

浏览:600

本文深入解析Brook JavaScript框架,阐述其基于UNIX Pipe概念的链式处理机制。详细讲解Promise、Channel、Model及Widget四大核心组件的使用方法,并通过代码示例展示如何利用这些特性构建清晰的MVC架构,实现模块与视图的有效分离与数据流转。

文章目录

Brook框架概述与核心特性

Brook框架借鉴了UNIX系统中的管道(pipe)理念,允许开发者将多个处理步骤串联起来协同工作。前一个处理步骤的输出直接作为下一个步骤的输入,从而实现参数的无缝传递。借助Brook,开发者能够以MVC(模型-视图-控制器)的模式来编写JavaScript应用程序。


项目主页:http://hirokidaichi.github.com/brook/,本站提供下载。


Brook框架依赖namespace库来组织模块结构。


以下通过示例再次说明namespace的具体用法:


代码如下:

 
// 定义一个sample命名空间
Namespace('sample')
// 使用brook
.use('brook *')
.use('brook.util *')
.define( function (ns) {
var foo = function() {
alert('this is sample.foo');
}; 
// 定义对外公开的函数
// 外部模块只要use了sample之后,就可以通过ns.sample.foo()来调用
ns.provide({
foo : foo
}); 
}); 
// 使用的例子
Namespace.use('sample').apply(function(ns) {
ns.sample.foo();
}); 


核心概念:Promise与管道处理

要深入理解Brook框架,必须掌握其几个核心概念。


promise


简而言之,promise是一个封装好的函数,负责将值传递给下一个promise。这类似于接力赛中传递接力棒(value)给下一位成员(promise)。这种机制使得非同步处理能够按照类似同步处理的顺序进行编程。


代码如下:

 
var p = ns.promise(function(next, value){
// 在这里对value进行处理
// value是之前的promise传递进来的
// 把工作移交给下一个promise
next("new_value");
}); 

接下来看看promise的实际应用场景。例如有以下需求:


等待一秒


输出moge


等待两秒


输出muga



不使用promise时的写法:


代码如下:

 
(function() {
var firstInterval = setInterval(function() {
console.log("moge");
clearInterval(firstInterval);
var secondInterval = setInterval(function() {
console.log("muga");
clearInterval(secondInterval);
}, 2000);
}, 1000);
})(); 

上述代码的执行顺序较难直观理解。如果改用promise,写法如下:


代码如下:

 
Namespace("sample")
.use("brook *")
.use("brook.util *")
.define(function(ns) {
var p1 = ns.promise(function(next, value) {
console.log("moge");
next("muga");
}); 
var p2 = ns.promise(function(next, value) {
console.log(value);
next();
}); 
ns.provide({
execute: function() {
ns.wait(1000).bind(p1).bind(ns.wait(2000)).bind(p2).run();
} 
}); 
}); 
Namespace.use("sample").apply(function(ns) {
ns.sample.execute();
}); 

其中bind函数可以接受多个参数,也可以写成这样:


ns.wait(1000).bind(p1, ns.wait(1000), p2).run();


promise的使用方法:


1:等待几秒可以使用brook.util下的wait方法


2:promise之间“棒的交接”是通过bind方法实现的,也就是UNIX下的PIPE功能。


3:最后需要执行run()方法


数据集合管理:Channel与Model

channel


channel顾名思义就是频道或管道的意思。在Brook中,它表示promise的集合。可以将多个promise存入一个channel,然后统一执行。


代码如下:

 
var p3 = ns.promise(function(next, value) {
console.log(value + "!");
}); 
var p4 = ns.promise(function(next, value) {
console.log(value + "!!");
}); 
ns.provide({
execute: function() {
var channel = ns.channel("testChannel");
channel.observe(p3);
channel.observe(p4);
ns.sendChannel("testChannel").run("hello");
} 
}); 

channel的使用方法:


1:observer:把promise追加到channel中


2:sendChannel:确定channel


3:最后通过run来执行channel里所有promise


model


model是对channel进行包装而成的。在model中可以定义带有名字的channel,这些channel即为一个个method。


该组件明确了MVC中的M(模型)和V(视图)。它可以实现这样的处理:model的method执行后,其结果传递到一个或多个view(promise)。这体现了观察者模式。


代码如下:

 
var requestFilter = ns.promise(function(v){
v["viewer_id"] = viewer.getID();
retrun v;
}); 
var create = ns.promise(function(n,v){
// get data
n(response);
}); 
var delete = ns.promise(function(n,v){
// get data
n(response);
}); 
var view1 = ns.promise(function(n,v){
// render html
n(v);
}); 
var view2 = ns.promise(function(n,v){
// render html
n(v);
}); 
var model = ns.createModel();
model.addMethod('create', ns.mapper(requestFilter).bind(create));
model.addMethod('delete', ns.mapper(requestFilter).bind(delete));
ns.from(model.method('create')).bind(view1).run();
ns.from(model.method('create')).bind(view2).run();
ns.promise().bind(model.notify('create').run({"body": "test"}));
//向view1和view2传递参数{"body": "test"}

model的使用方法:


:ns.createModel():生成model


:model.addMethod():定义method名和相应的处理promise


:ns.from():定义model的某个method执行完之后的处理


:model.notify():执行model的method


视图关联:Widget组件应用

widget


widget负责将HTML元素与命名空间模块关联起来。看一个简单的例子。


首先定义一个sample.widget的namespace。


代码如下:

 
// sample-widget.js
Namespace("sample.widget")
.use("brook.widget *")
.define(function(ns) {
ns.provide({
registerElement: function(element) {
element.innerHTML = "Hello World!";
} 
}); 
}); 

下面是关于sample.widget的HTML页面。


代码如下:

 
<html>
<head>
<title>widget sample</title>
<script type="text/javascript" src="js/namespace.js"></script>
<script type="text/javascript" src="js/brook.js"></script>
<script type="text/javascript" src="js/sample-widget.js"></script>
</head>
<body>
<h1>widget</h1>
<div class="widget" data-widget-namespace="sample.widget">hoge</div>
<div class="widget" data-widget-namespace="sample.widget">foo</div>
<div class="widget" data-widget-namespace="sample.widget">bar</div>
<script type="text/javascript">
//entry point
Namespace.use("brook.widget *").apply(function(ns) {
ns.bindAllWidget.run();
}); 
</script>
</body>
</html>

这段代码会将data-widget-namespace指定为sample.widget的div内容全部置换成hello world!


执行控制:run与subscribe的区别

run()和subscribe()的区别


promise执行时需要使用run()方法。当一个promise链处理完毕需要执行回调函数时,不使用run,而是使用subscribe。


代码如下:

 
ns.promise().bind(function(next, value) {
next(value);
}).subscribe(function(value) {
console.log(value, "world!");
}, "hello");
//hello world!
ns.promise().bind(function(next, value) {
console.log(value);
next("no next");
}).run("hello");
//hello

实用工具模块:brook.util详解

brook.util


这个模块里面定义很多有用的方法。


mapper:定义装饰处理


代码如下:

 
var input = ns.promise(function(next, value) {
next("this is input");
}); 
var mapper = ns.mapper(function(value) {
return value + "!";
}); 
var output = ns.promise(function(next, value) {
console.log(value);
next(value);
}); 
//执行
input.bind(mapper).bind(output).run();
//this is input!

filter:过滤器


代码如下:

 
var input = ns.promise(function(next, value) {
next(2);
}); 
var evenFilter = ns.filter(function(value) {
return (value % 2) === 0;
}); 
var output = ns.promise(function(next, value) {
console.log(value + " is even");
next(value);
}); 
//执行
input.bind(evenFilter).bind(output).run();
//2 is even

scatter:分散器,value里面的值依次调用下一个promise


代码如下:

 
var output = ns.promise(function(next, value) {
console.log(value);
next(value);
}); 
//执行
ns.scatter().bind(output).run([1, 2, 3, 4, 5, 6]);
//1
//2
//3
//4
//5
//6

takeBy:从value里面一次取n个调用下一个promise


代码如下:

 
var output = ns.promise(function(next, value) {
console.log(value);
next(value);
}); 
//実行
ns.scatter().bind(ns.takeBy(2)).bind(output).run([1, 2, 3, 4, 5, 6]);
//[1, 2]
//[3, 4]
//[5, 6]

wait:等待n毫秒


cond:有条件执行promise,第一个参数是过滤器,第二个参数是promise。第一个参数为true的时候执行第二个参数的promise。


代码如下:

 
var output = ns.promise(function(next, value) {
console.log(value);
next(value);
}); 
var isEven = function(num) {
return (num % 2 === 0);
}; 
var done = ns.promise(function(next, value) {
console.log("done");
}); 
//実行
ns.cond(isEven, output).bind(done).run(2);
//2
//done
ns.cond(isEven, output).bind(done).run(3);
//done

match:根据value的值来决定执行哪一个promise。


代码如下:

 
var dispatchTable = {
"__default__": ns.promise(function(next, value) {
console.log("default");
}), 
"hello": ns.promise(function(next, value) {
console.log("hello");
}), 
"world": ns.promise(function(next, value) {
console.log("world");
}) 
}; 
ns.match(dispatchTable).run("hello");
ns.match(dispatchTable).run("world");
ns.match(dispatchTable).run("hoge");

from:为promise链传递初始参数,也可以用run来传递。


代码如下:

 
ns.from("hello").bind(ns.debug()).run();
//debug: hello

最后还可以通过github首页的例子来体会,brook是怎么实现MVC模式的。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章