JavaScript系列(70)--响应式编程进阶详解

news2025/2/12 6:39:58

JavaScript响应式编程进阶详解 🔄

今天,让我们深入探讨JavaScript响应式编程的进阶内容。响应式编程是一种强大的编程范式,它能够帮助我们更好地处理异步数据流和状态管理。

响应式编程进阶概念 🌟

💡 小知识:响应式编程的核心是数据流,通过操作符(operators)对数据流进行转换、组合和过滤,从而实现复杂的业务逻辑。高阶响应式编程更关注性能优化和复杂场景处理。

自定义响应式系统实现 📊

// 1. 响应式数据核心
class Observable {
    constructor(subscribe) {
        this._subscribe = subscribe;
    }
    
    subscribe(observer) {
        if (typeof observer === 'function') {
            observer = { next: observer };
        }
        
        return this._subscribe(observer);
    }
    
    // 操作符工厂方法
    pipe(...operators) {
        return operators.reduce((source, operator) => operator(source), this);
    }
    
    // 静态创建方法
    static from(input) {
        if (Array.isArray(input)) {
            return new Observable(observer => {
                input.forEach(value => observer.next(value));
                observer.complete();
                return () => {};
            });
        }
        
        if (input[Symbol.iterator]) {
            return Observable.from([...input]);
        }
        
        throw new Error('Unsupported input type');
    }
    
    static of(...items) {
        return Observable.from(items);
    }
}

// 2. 响应式主体
class Subject extends Observable {
    constructor() {
        super();
        this.observers = new Set();
    }
    
    next(value) {
        for (const observer of this.observers) {
            observer.next(value);
        }
    }
    
    error(error) {
        for (const observer of this.observers) {
            observer.error?.(error);
        }
    }
    
    complete() {
        for (const observer of this.observers) {
            observer.complete?.();
        }
        this.observers.clear();
    }
    
    subscribe(observer) {
        this.observers.add(observer);
        
        return {
            unsubscribe: () => {
                this.observers.delete(observer);
            }
        };
    }
}

// 3. 行为主体
class BehaviorSubject extends Subject {
    constructor(initialValue) {
        super();
        this._value = initialValue;
    }
    
    get value() {
        return this._value;
    }
    
    next(value) {
        this._value = value;
        super.next(value);
    }
    
    subscribe(observer) {
        const subscription = super.subscribe(observer);
        observer.next(this._value);
        return subscription;
    }
}

高级操作符实现 🚀

// 1. 转换操作符
const operators = {
    // 映射操作符
    map: (project) => (source) =>
        new Observable(observer => {
            return source.subscribe({
                next: value => observer.next(project(value)),
                error: err => observer.error(err),
                complete: () => observer.complete()
            });
        }),
    
    // 过滤操作符
    filter: (predicate) => (source) =>
        new Observable(observer => {
            return source.subscribe({
                next: value => {
                    if (predicate(value)) {
                        observer.next(value);
                    }
                },
                error: err => observer.error(err),
                complete: () => observer.complete()
            });
        }),
    
    // 去重操作符
    distinct: (keySelector = x => x) => (source) =>
        new Observable(observer => {
            const seen = new Set();
            
            return source.subscribe({
                next: value => {
                    const key = keySelector(value);
                    if (!seen.has(key)) {
                        seen.add(key);
                        observer.next(value);
                    }
                },
                error: err => observer.error(err),
                complete: () => observer.complete()
            });
        }),
    
    // 扁平化操作符
    mergeMap: (project) => (source) =>
        new Observable(observer => {
            let active = 0;
            let completed = false;
            
            const checkComplete = () => {
                if (completed && active === 0) {
                    observer.complete();
                }
            };
            
            const outerSubscription = source.subscribe({
                next: value => {
                    active++;
                    const innerObservable = project(value);
                    
                    innerObservable.subscribe({
                        next: innerValue => observer.next(innerValue),
                        error: err => observer.error(err),
                        complete: () => {
                            active--;
                            checkComplete();
                        }
                    });
                },
                error: err => observer.error(err),
                complete: () => {
                    completed = true;
                    checkComplete();
                }
            });
            
            return outerSubscription;
        })
};

// 2. 组合操作符
const combinationOperators = {
    // 合并多个Observable
    merge: (...sources) =>
        new Observable(observer => {
            let completed = 0;
            const subscriptions = sources.map(source =>
                source.subscribe({
                    next: value => observer.next(value),
                    error: err => observer.error(err),
                    complete: () => {
                        completed++;
                        if (completed === sources.length) {
                            observer.complete();
                        }
                    }
                })
            );
            
            return {
                unsubscribe: () => {
                    subscriptions.forEach(sub => sub.unsubscribe());
                }
            };
        }),
    
    // 组合最新值
    combineLatest: (...sources) =>
        new Observable(observer => {
            const values = new Array(sources.length);
            const hasValue = new Array(sources.length).fill(false);
            let completed = 0;
            
            const checkComplete = () => {
                if (completed === sources.length) {
                    observer.complete();
                }
            };
            
            const subscriptions = sources.map((source, index) =>
                source.subscribe({
                    next: value => {
                        values[index] = value;
                        hasValue[index] = true;
                        
                        if (hasValue.every(Boolean)) {
                            observer.next([...values]);
                        }
                    },
                    error: err => observer.error(err),
                    complete: () => {
                        completed++;
                        checkComplete();
                    }
                })
            );
            
            return {
                unsubscribe: () => {
                    subscriptions.forEach(sub => sub.unsubscribe());
                }
            };
        })
};

// 3. 错误处理操作符
const errorOperators = {
    // 重试操作符
    retry: (count = 3) => (source) =>
        new Observable(observer => {
            let retries = 0;
            
            function subscribe() {
                return source.subscribe({
                    next: value => observer.next(value),
                    error: err => {
                        if (retries < count) {
                            retries++;
                            subscribe();
                        } else {
                            observer.error(err);
                        }
                    },
                    complete: () => observer.complete()
                });
            }
            
            return subscribe();
        }),
    
    // 捕获错误操作符
    catchError: (selector) => (source) =>
        new Observable(observer => {
            return source.subscribe({
                next: value => observer.next(value),
                error: err => {
                    try {
                        const result = selector(err);
                        result.subscribe(observer);
                    } catch (e) {
                        observer.error(e);
                    }
                },
                complete: () => observer.complete()
            });
        })
};

性能优化实现 ⚡

// 1. 调度器实现
class Scheduler {
    constructor() {
        this.queue = new Map();
        this.running = false;
    }
    
    schedule(task, delay = 0) {
        return new Promise((resolve, reject) => {
            const timeoutId = setTimeout(() => {
                this.queue.set(timeoutId, {
                    task,
                    resolve,
                    reject
                });
                this.runTasks();
            }, delay);
        });
    }
    
    async runTasks() {
        if (this.running) return;
        this.running = true;
        
        try {
            for (const [id, { task, resolve, reject }] of this.queue) {
                try {
                    const result = await task();
                    resolve(result);
                } catch (error) {
                    reject(error);
                } finally {
                    this.queue.delete(id);
                }
            }
        } finally {
            this.running = false;
        }
    }
}

// 2. 内存优化
class MemoryOptimizedSubject extends Subject {
    constructor(options = {}) {
        super();
        this.bufferSize = options.bufferSize || 1;
        this.buffer = [];
    }
    
    next(value) {
        this.buffer.push(value);
        if (this.buffer.length > this.bufferSize) {
            this.buffer.shift();
        }
        super.next(value);
    }
    
    subscribe(observer) {
        // 发送缓冲区的值
        this.buffer.forEach(value => observer.next(value));
        return super.subscribe(observer);
    }
}

// 3. 批处理优化
class BatchProcessor {
    constructor(options = {}) {
        this.batchSize = options.batchSize || 100;
        this.flushInterval = options.flushInterval || 1000;
        this.buffer = [];
        this.subject = new Subject();
        this.setupAutoFlush();
    }
    
    add(item) {
        this.buffer.push(item);
        
        if (this.buffer.length >= this.batchSize) {
            this.flush();
        }
    }
    
    flush() {
        if (this.buffer.length > 0) {
            this.subject.next([...this.buffer]);
            this.buffer = [];
        }
    }
    
    setupAutoFlush() {
        setInterval(() => this.flush(), this.flushInterval);
    }
    
    subscribe(observer) {
        return this.subject.subscribe(observer);
    }
}

最佳实践建议 💡

  1. 响应式设计模式
// 1. 响应式状态管理
class ReactiveStore {
    constructor(initialState = {}) {
        this.state = new BehaviorSubject(initialState);
        this.actions = new Subject();
        this.setupReducer();
    }
    
    setupReducer() {
        this.actions.pipe(
            operators.scan((state, action) => {
                const newState = this.reducer(state, action);
                return newState;
            }, this.state.value)
        ).subscribe(this.state);
    }
    
    dispatch(action) {
        this.actions.next(action);
    }
    
    select(selector) {
        return this.state.pipe(
            operators.map(selector),
            operators.distinct()
        );
    }
}

// 2. 响应式缓存
class ReactiveCache {
    constructor(ttl = 60000) {
        this.cache = new Map();
        this.ttl = ttl;
        this.cleanup();
    }
    
    get(key) {
        const entry = this.cache.get(key);
        if (!entry) return null;
        
        if (Date.now() - entry.timestamp > this.ttl) {
            this.cache.delete(key);
            return null;
        }
        
        return entry.value;
    }
    
    set(key, value) {
        this.cache.set(key, {
            value,
            timestamp: Date.now()
        });
    }
    
    cleanup() {
        setInterval(() => {
            const now = Date.now();
            for (const [key, entry] of this.cache.entries()) {
                if (now - entry.timestamp > this.ttl) {
                    this.cache.delete(key);
                }
            }
        }, this.ttl);
    }
}

// 3. 响应式事件总线
class EventBus {
    constructor() {
        this.subjects = new Map();
    }
    
    on(event) {
        if (!this.subjects.has(event)) {
            this.subjects.set(event, new Subject());
        }
        return this.subjects.get(event);
    }
    
    emit(event, data) {
        const subject = this.subjects.get(event);
        if (subject) {
            subject.next(data);
        }
    }
    
    off(event) {
        const subject = this.subjects.get(event);
        if (subject) {
            subject.complete();
            this.subjects.delete(event);
        }
    }
}

结语 📝

响应式编程是一种强大的编程范式,掌握其进阶特性可以帮助我们构建更加健壮和可维护的应用。通过本文,我们学习了:

  1. 响应式编程的进阶概念和原理
  2. 自定义响应式系统的实现
  3. 高级操作符的实现和应用
  4. 性能优化技巧
  5. 最佳实践和设计模式

💡 学习建议:在实践响应式编程时,要注意内存管理和性能优化,合理使用操作符组合,同时要建立完善的错误处理机制。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2296709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

头条百度批量采集软件说明文档

旧版说明文档《头条号文章批量采集软件4.0版本说明文档&#xff01;头条/微头条文章批量采集》 头条的采集软件已经更新了好多个版本了&#xff0c;一直没有做详细的介绍文档&#xff0c;最近更新了一些功能进去&#xff0c;一块来写一下说明文档。 1、主界面 2、头条作者采集…

【面试】面试常见的智力题

引言 在技术面试中&#xff0c;除了考察编程能力和算法知识外&#xff0c;智力题也是常见的考察方式。智力题不仅能够测试候选人的逻辑思维能力&#xff0c;还能反映其解决问题的创造力和应变能力。本文将整理一些常见的面试智力题&#xff0c;并详细分析解题思路&#xff0c;…

【动态规划】风扫枯杨,满地堆黄叶 - 9. 完全背包问题

本篇博客给大家带来的是完全背包问题之动态规划解法技巧. &#x1f40e;文章专栏: 动态规划 &#x1f680;若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅&#x1f680; 要开心要快乐顺…

BGP基础协议详解

BGP基础协议详解 一、BGP在企业中的应用二、BGP概述2.1 BGP的特点2.2 基本配置演示2.3 抓包观察2.4 BGP的特征三、BGP对等体关系四、bgp报文4.1 BGP五种报文类型(重点)4.2 BGP报文格式-报文头格式4.3 Open报文格式4.4 Update报文格式4.5 Notification报文格式4.6 Route-refre…

LeetCode刷题---数组---840

矩阵中的幻方 https://leetcode.cn/problems/magic-squares-in-grid/submissions/598584907/ 题目&#xff1a; 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成…

Visual Studio踩过的坑

统计Unity项目代码行数 编辑-查找和替换-在文件中查找 查找内容输入 b*[^:b#/].*$ 勾选“使用正则表达式” 文件类型留空 也有网友做了指定&#xff0c;供参考 !*\bin\*;!*\obj\*;!*\.*\*!*.meta;!*.prefab;!*.unity 打开Unity的项目 注意&#xff1a;只是看&#xff0…

【深度学习入门实战】基于Keras的手写数字识别实战(附完整可视化分析)

​ 本人主页:机器学习司猫白 ok,话不多说,我们进入正题吧 项目概述 本案例使用经典的MNIST手写数字数据集,通过Keras构建全连接神经网络,实现0-9数字的分类识别。文章将包含: 关键概念图解完整实现代码训练过程可视化模型效果深度分析环境准备 import numpy as np impo…

SkyWalking 10.1.0 实战:从零构建全链路监控,解锁微服务性能优化新境界

文章目录 前言一、集成SkyWalking二、SkyWalking使用三、SkyWalking性能剖析四、SkyWalking 告警推送4.1 配置告警规则4.2 配置告警通知地址4.3 下发告警信息4.4 测试告警4.5 慢SQL查询 总结 前言 在传统监控系统中&#xff0c;我们通过进程监控和日志分析来发现系统问题&…

【通俗易懂说模型】反向传播(附多元分类与Softmax函数)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;深度学习_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. …

128,【1】buuctf [极客大挑战 2019]PHP

进入靶场 提示了备份文件 抓包&#xff0c;扫描 扫描出了两个有反应的 访问index.php没反应&#xff0c;但www.zip成功下载了文件 index.php里得到如下有用信息 <?phpinclude class.php;$select $_GET[select];$resunserialize($select);?> 所以我们要通过GET 方…

系统思考—双环学习

前几天&#xff0c;一个企业高管向我提到&#xff1a;“我们调整了N次方案&#xff0c;市场策略、团队激励、管理制度&#xff0c;能改的全改了&#xff0c;怎么还是不见起色&#xff1f;” 这让我想到典型的单环学习&#xff0c;简单来说就是&#xff1a;发现问题 → 采取行动…

QTreeView和QTableView单元格添加超链接

QTreeView和QTableView单元格添加超链接的方法类似,本文仅以QTreeView为例。 在QTableView仿Excel表头排序和筛选中已经实现了超链接的添加,但是需要借助delegate,这里介绍一种更简单的方式,无需借助delegate。 一.效果 二.实现 QHTreeView.h #ifndef QHTREEVIEW_H #def…

【MySQL篇】行格式详解

MySQL行格式详解 文章目录 MySQL行格式详解&#x1f389; 什么是行格式&#x1f431;‍&#x1f464; 如何查看行格式&#x1f431;‍&#x1f680; InnoDB 行格式有哪些&#xff1f;&#x1f431;‍&#x1f3cd; Compact 行格式&#x1f6a9; 额外信息&#x1f680; 变长字段…

嵌入式知识点总结 操作系统 专题提升(五)-内存

针对于嵌入式软件杂乱的知识点总结起来&#xff0c;提供给读者学习复习对下述内容的强化。 目录 1.在1G内存的计算机能否malloc&#xff08;1.2G&#xff09;&#xff1f;为什么&#xff1f; 2.malloc能申请多大的空间&#xff1f; 3.内存管理有哪几种方式&#xff1f; 4.什…

动手学深度学习---深层神经网络

目录 一、神经网络1.1、模型训练1.2、损失函数1.2.1、分类&#xff1a;hinge loss/合页损失/支持向量机损失1.2.2、分类&#xff1a;交叉熵损失(softmax分类器)1.2.2.1 二分类交叉熵损失1.2.2.2 多分类交叉熵损失 1.2.3、回归&#xff1a;误差平方和&#xff08;SSE&#xff09…

java基础6(黑马)

一、static 1.static修饰成员变量 static&#xff1a;叫静态&#xff0c;可以修饰成员变量、成员方法。 成员变量按照有无static&#xff0c;分两种。 类变量&#xff1a;有static修饰&#xff0c;属于类&#xff0c;在计算机中只有一份&#xff0c;会被类的全部对象共享。…

Transformer 详解:了解 GPT、BERT 和 T5 背后的模型

目录 什么是 Transformer? Transformer如何工作? Transformer 为何有用? 常见问题解答:机器学习中的 Transformer 在技​​术领域,突破通常来自于修复损坏的东西。制造第一架飞机的人研究过鸟类。莱特兄弟观察了秃鹫如何在气流中保持平衡,意识到稳定性比动力更重要。…

【Prometheus】MySQL主从搭建,以及如何通过prometheus监控MySQL运行状态

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

百问网imx6ullpro调试记录(linux+qt)

调试记录 文章目录 调试记录进展1.开发板相关1.1百问网乌班图密码 1.2 换设备开发环境搭建串口调试网络互通nfs文件系统挂载 1.3网络问题1.4系统启动1.5进程操作 2.QT2.1tslib1.获取源码2.安装依赖文件3.编译 2.2qt移植1.获取qt源码2.配置编译器3.编译 2.3拷贝到开发板1.拷贝2.…

人脸识别与人脸检测技术

人脸识别技术,作为一种基于人的脸部特征信息进行身份识别的生物识别技术,近年来在人工智能和计算机视觉技术的推动下取得了显著进展。它利用摄像机或摄像头采集含有人脸的图像或视频流,自动在图像中检测和跟踪人脸,进而对检测到的人脸进行一系列计算和分别判断。这一技术不…