[Cycle.js] Read effects from the DOM: click events
2016-02-02 23:11
375 查看
So far we only had effects that write something to the external world, we are not yet reading anything from the external world into our app. This lesson shows how we can change the DOM Driver to return a "DOM Source" representing read effects, such as click events. We will leverage that to create an interactive application.
Source: stands for input, read effect
sink: stands for output, write effect
So main() function need to take a param 'DOMSource' and effects function need return value:
The problem in the code above is that:
the main function need param 'DOMSource' which is returned by the driver DOMDriver. But for create DOMSource in run() function, we need pass DOMSource to the main() function. So 'DOMSource' is actually used before it created.
I can simply the problem as:
a = f(b); // we need b to create a
b = g(a) // we need a to create b
So there is a cycle going on between main() function and driver() function.
The solution to sovle this problem is :
A is an observable and also B is an observable. If we actually instead of using B, we could use something like B proxy here. Because B proxy is now available for f() as an argument.
Then that helps us to make A, and then given A we can make B. Then now that we have B, we can feed back all of the events that happen on B into B proxy. So that's what we're going to try to achieve.
bProxy = ...
a = f(bProxy)
b = g(a)
bProxy.imitat(b)
So the code looks like:
// Logic (functional) function main() { return { DOM: Rx.Observable.timer(0, 1000) .map(i => `Seconds elapsed ${i}`), Log: Rx.Observable.timer(0, 2000).map(i => 2*i), }; } // Effects (imperative) function DOMEffect(text$) { text$.subscribe(text => { const container = document.querySelector('#app'); container.textContent = text; }); } function consoleLogEffect(msg$) { msg$.subscribe(msg => console.log(msg)); } const effects = { DOM: DOMEffect, Log: consoleLogEffect } function run(mainFn, effects){ const sinks = mainFn(); Object.keys(effects) .forEach( (effectKey)=>{ effects[effectKey](sinks[effectKey]); }) } run(main, effects);
Source: stands for input, read effect
sink: stands for output, write effect
So main() function need to take a param 'DOMSource' and effects function need return value:
function main(DOMSource) { ... } function DOMDriver() { ... const DOMSource = Rx.Observable.fromEvent(document, 'clicik'); return DOMSource; } function run(mainFn, drivers) { const sinks = mainFn(DOMSource); const DOMSource = drivers['DOM'](sinks['DOM']) .... }
The problem in the code above is that:
the main function need param 'DOMSource' which is returned by the driver DOMDriver. But for create DOMSource in run() function, we need pass DOMSource to the main() function. So 'DOMSource' is actually used before it created.
I can simply the problem as:
a = f(b); // we need b to create a
b = g(a) // we need a to create b
So there is a cycle going on between main() function and driver() function.
The solution to sovle this problem is :
A is an observable and also B is an observable. If we actually instead of using B, we could use something like B proxy here. Because B proxy is now available for f() as an argument.
Then that helps us to make A, and then given A we can make B. Then now that we have B, we can feed back all of the events that happen on B into B proxy. So that's what we're going to try to achieve.
bProxy = ...
a = f(bProxy)
b = g(a)
bProxy.imitat(b)
So the code looks like:
// Logic (functional) function main(DOMSource) { const click$ = DOMSource; return { DOM: click$ .startWith(null) .flatMapLatest(() => Rx.Observable.timer(0, 1000) .map(i => `Seconds elapsed ${i}`) ), Log: Rx.Observable.timer(0, 2000).map(i => 2*i), }; } // source: input (read) effects // sink: output (write) effects // Effects (imperative) function DOMDriver(text$) { text$.subscribe(text => { const container = document.querySelector('#app'); container.textContent = text; }); const DOMSource = Rx.Observable.fromEvent(document, 'click'); return DOMSource; } function consoleLogDriver(msg$) { msg$.subscribe(msg => console.log(msg)); } // bProxy = ... // a = f(bProxy) // b = g(a) // bProxy.imitate(b) function run(mainFn, drivers) { const proxyDOMSource = new Rx.Subject(); const sinks = mainFn(proxyDOMSource); const DOMSource = drivers.DOM(sinks.DOM); DOMSource.subscribe(click => proxyDOMSource.onNext(click)); // Object.keys(drivers).forEach(key => { // drivers[key](sinks[key]); // }); } const drivers = { DOM: DOMDriver, Log: consoleLogDriver, } run(main, drivers);
相关文章推荐
- 个人笔记 js 14 js实现点击单元格行跳转链接到指定页面
- 小白Html5学习日记01
- HTML5(八)canvas转换之万花筒
- extjs查找表单中的文本框值
- 个人笔记 js 13 点击事件触发弹窗询问选项
- 个人笔记 html 04 提交表单与跳转页面冲突时
- AngularJS中实现Model缓存
- [转]FastJSON通过SerializeFilter定制序列化
- 【Prufer数列/组合数学】[HNOI2008][HYSBZ/BZOJ1005]明明的烦恼
- #学习笔记#(30)牛客网JS测试题21~45
- js调试工具Console命令详解
- node.js 资料
- 自己定义html中a标签的title提示tooltip
- 如何实现JSP网页模板 JSP网页母版
- HTML-03表单的创建
- Angular依赖注入详解
- Reactor构架模式
- javascript异步过程
- BZOJ 1013: [JSOI2008]球形空间产生器sphere
- Karma的第一次使用