[Functional Programming] Use the Callback and Closure Pattern to Build Advanced Async Behaviors [Full code]
2023-09-14 09:00:46 时间
import { curry, compose, toUpper, pipe } from 'ramda'; // #region listeners const _log = (value) => console.log(value); // #endregion // #region broadcasters const done = Symbol('done'); const addListener = curry((element, eventType, listener) => { return element.addEventListener(evenType, listener); }); const createInterval = curry((time, listener) => { let i = 0; const id = setInterval(() => { listener(i++); }, time); return () => { clearInterval(id); }; }); const createForOf = curry((iterator, listener) => { const id = setTimeout(() => { for (let item of iterator) { listener(item); } listener(done); }, 0); return () => { clearTimeout(id); }; }); const createZipOf = curry((broadcaster1, broadcaster2, listener) => { let cancelBoth; let buffer1 = []; const cancel1 = broadcaster1((value) => { buffer1.push(value); if (buffer2.length) { listener([buffer1.shift(), buffer2.shift()]); if (buffer1[0] === done || buffer2[0] === done) { listener(done); cancelBoth(); } } }); let buffer2 = []; const cancel2 = broadcaster2((value) => { buffer2.push(value); if (buffer1.length) { listener([buffer1.shift(), buffer2.shift()]); if (buffer1[0] === done || buffer2[0] === done) { listener(done); cancelBoth(); } } }); cancelBoth = () => { cancel1(); cancel2(); }; return cancelBoth; }); // #endregion // #region operators const createOperator = curry((operator, broadcaster, listener) => { // new a new broadcaster and invoke original broadcaster inside new broadcaster return operator((behaviorListener) => { // override the default broadcaster return broadcaster(value => { // apply common logic if(value === done) { // stop outer listen to continue emitting values listener(done) return } // otherwise, we want to pass forward the value to listener behaviorListener(value) }) }, listener) }) const concat = createOperator((broadcaster, listener) => { let string = ''; return broadcaster((value) => { listener((string += value)); }); }); const map = transform => createOperator((broadcaster, listener) => { return broadcaster((value) => { listener(transform(value)); }); }); const filter = predicator => createOperator((broadcaster, listener) => { return broadcaster((value) => { if (predicator(value)) { listener(value); } }); }); const split = splitter => curry((broadcaster, listener) => { let buffer = [] return broadcaster((value) => { if (value === done) { listener(buffer) listener(done) buffer = [] } if (value === splitter) { listener(buffer) buffer = [] } else { buffer.push(value) } }) }) // #endregion const transform = pipe( map((x) => x[1]), filter((x) => x !== ','), map(toUpper), split(" ") ); let typeGreeting = transform( createZipOf(createInterval(100), createForOf('My Zipo')) ); const cancelGreating = typeGreeting((value => { if(value === done) { _log("Shut down") return } _log(value) })) // cancelGreating() const myZip = (boradcaster1, boradcaster2) => (...operators) => { return pipe(...operators)(createZipOf(boradcaster1, boradcaster2)) } const typeGreeting2 = myZip( // boradcasters createInterval(100), createForOf('My Zipo') )( // operators map((x) => x[1]), filter((x) => x !== ','), concat, map(toUpper) ) const cancelGreating2 = typeGreeting2(_log) // cancelGreating2()
相关文章
- 一文吃透 VS Code+Git 操作(vs code中git的相关配置与使用)
- How to code like a pro in 2022 and avoid If-Else
- Daily Code 365 | 01 整数转罗马数字
- laravel发送邮件时报Expected response code 250 but got code "530"....错误
- maven deploy报错:Return code is: 401, ReasonPhrase: Unauthorized. ->
- 【已解决】在使用RocketMQ消费消息的时候,提示不支持SQL92的错误:CODE: 1 DESC: The broker does not support consumer to filter
- 牛逼!ChatGPT 中文版 VS Code 插件来了!免登录、免注册
- ORA-32511: cannot create watchpoint in memory needed by watchpointing code ORACLE 报错 故障修复 远程处理
- ORA-48001: internal error code, arguments: [string], [string], [string], [string], [string], [string], [string], [string] ORACLE 报错 故障修复 远程处理
- ORA-13136: null common code generated ORACLE 报错 故障修复 远程处理
- Oracle 参数 PLSQL_CODE_TYPE 官方解释,作用,如何配置最优化建议
- Code_scanner-采购订单取消默认K的增强详解编程语言
- VS Code运行Python程序
- How to Compile Redis from Source Code: A StepbyStep Guide(redis源码编译)
- Exploring the Linux Kernel: Analyzing the Network Source Code(linux内核网络源代码)
- VS Code 与 MSSQL 的完美融合(vscode mssql)
- asp.net中将表单提交到另一页Code-Behind(代码和html在不同的页面)