[Cycle.js] Read effects from the DOM: click events
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.
// 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);
相关文章
- Maven报错:The packaging for this project did not assign a file to the build artifact[通俗易懂]
- 基于H5+js开发一款音乐播放器
- 用JS获取地址栏url参数的方法_js的url是啥
- 爆肝整理高频js手写题请查收
- vue前端怎么解决跨域问题_前端跨域调用js方法解决方案
- Node.JS 安装配置 | 安装排错解析
- 解决The HTTP request is not acceptable for the requested resource
- 原生 JS 实现 HTML 转 Markdown,以及其实现逻辑(html2md.js 或 html2markdown.js)
- js本地存储:localStorage
- Error fetching command 'build_solr_schema': The 'solr' backend requires the installation of 'pysolr'
- ORA-48442: The control parameter number exceeds the maximum number [string] ORACLE 报错 故障修复 远程处理
- ORA-48485: The file exceeds the maximum length [string] ORACLE 报错 故障修复 远程处理
- ORA-48487: The internal predicate string exceeds the maximum length [string] ORACLE 报错 故障修复 远程处理
- ORA-53410: The attribute string does not conform to the VM rule. ORACLE 报错 故障修复 远程处理
- ORA-08119: The new initrans will make the index too big ORACLE 报错 故障修复 远程处理
- the cloudTaking Oracle to the Cloud: The Evolution of Database Systems(oracleisin)
- The Power of the Hydra Oracle: Unlocking Potential(hydraoracle)
- Exploring the versatility of Linux: The significance of the var directory(linux系统var)
- 使用JS技术实现Oracle数据库链接(js 链接 oracle)
- JS实时链接Oracle让数据库访问更便捷(js实时连接oracle)
- GoogleSuggest;-)基于js的动态下拉菜单
- 浅说js变量
- js获取坐标通过JS得到当前焦点(鼠标)的坐标属性
- 用JS将搜索的关键字高亮显示实现代码
- js中数组(Array)的排序(sort)注意事项说明
- js显示base64编码的二进制流网页图片
- js动态控制table的tr、td增加及删除的具体实现
- node.js中的定时器nextTick()和setImmediate()区别分析
- JS循环遍历JSON数据的方法
- 了不起的node.js读书笔记之node.js中的特性
- asp.net后台动态添加JS文件和css文件的引用实现方法