前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >三连弹!原生实现异步处理利器 —— Observable

三连弹!原生实现异步处理利器 —— Observable

作者头像
掘金安东尼
发布2022-09-19 10:59:41
2940
发布2022-09-19 10:59:41
举报
文章被收录于专栏:掘金安东尼

这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战


本篇译自:https://javascript.plainenglish.io/how-to-use-observables-with-vanilla-javascript

接上两篇:

我们认识了 ES7 处理异步的一大利器 —— Observable

本篇带来用原生实现 Observable,一探内部究竟!!

实现步骤解析如下:

  1. Observable 应该是一个 Subject 新对象类型;
  2. 并且 Subject 对象有subscribenext两个函数;
  3. subscribe 由 observers (观察者)调用,来订阅可观察的数据流;
  4. nextSubject owner 调用,实现推送/发布新数据;
  5. Subject owner 应该知道 observers 何时监听数据生效;
  6. 另外,Subject owner 也应该知道 observers 何时不再监听了;
  7. 再看 observer,它也应该可以随时被取消;
  8. 可以定义一个新的对象,Subscription
  9. Subscription 包含 unsubscribe 函数;
  10. 每个 observer 想要停止监听来自 Subject 的数据流时,可以调用unsubscribe实现;

有了以上思路之后,我们可以进一步来看代码实现~


代码实现:

Subscription

代码语言:javascript
复制
let Subscription = function(handlerId, unsubscribeNotificationCallback) {
    let self = this;

    self.unsubscribe = () => {
        if(unsubscribeNotificationCallback) {
            unsubscribeNotificationCallback(handlerId);
        }
    };
    
    return self;
};

注意:Subscription 仅在 unsubscribe 被调用时,通知 Subject


再看 Subject 完整代码实现:

代码语言:javascript
复制
let Subject = function(subscribersStateChangeNotificationCallback) {
    let self = this;
    
    let handlers = {};
    
    Object.defineProperty(self, "subscribersFound", {
        get() {
            let found = false;
            
            for(const prop in handlers) {
                if(handlers.hasOwnProperty(prop)) {
                    found = true;
                    break;
                }
            }
            
            return found;
        }
    });
    
    Object.defineProperty(self, "subscribersCount", {
        get() {
            let count = 0;
            
            for(const prop in handlers) {
                if(handlers.hasOwnProperty(prop)) {
                    count++;
                }
            }
            
            return count;
        }
    });
    
    let unsubscribeNotificationCallback = (handlerId) => {
        if(handlerId && handlerId !== '' && handlers.hasOwnProperty(handlerId)) {
            delete handlers[handlerId];
            
            if(subscribersStateChangeNotificationCallback && !self.subscribersFound) {
                subscribersStateChangeNotificationCallback(false);
            }
        }
    };
    
    self.subscribe = (handler) => {
        let handlerId = createGuid();
        handlers[handlerId] = handler;
        
        if(subscribersStateChangeNotificationCallback && self.subscribersCount === 1) {
            subscribersStateChangeNotificationCallback(true);
        }
        
        return new Subscription(handlerId, unsubscribeNotificationCallback);
    };
    
    self.next = (data) => {
        for(const handlerId in handlers) {
            handlers[handlerId](data);
        }
    };
    
    return self;
};

let createGuid = function() {  
   return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {  
      var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);  
      return v.toString(16);  
   });  
};

Subject Owner 实现:

代码语言:javascript
复制
.
.
.
let subscribersStateChangeNotificationCallback = (subscriberFound) => {
    if(!subscriberFound && isNowWatching) {
        stopWatching();
        isNowWatching = false;
    } else if(subscriberFound && !isNowWatching) {
        startWatching();
    }
};

self.data = new Subject(subscribersStateChangeNotificationCallback);
.
.
.
self.data.next(self.snapshot.data);
.
.
.

Observer 实现:

代码语言:javascript
复制
.
.
.
const dashboardServiceSubscription = myDashboardService.data.subscribe((data) => {
    ...
});
.
.
.
dashboardServiceSubscription.unsubscribe();
.
.
.

小结:我们可以看到实现关键是 Subject 对象,更重要的是 发布订阅 的过程!当然,也不能忘了 取消订阅 的功能;

发布和订阅模式来处理异步可以忽视掉时间这个维度,就是不用管时间上的先后,就保证了顺序!这一点,在前面一篇函数式编程中也讲过:《XDM,JS如何函数式编程?看这就够了!(六)》 —— 减少时间状态!

不得不说,都是相通的~~ Σ(⊙▽⊙"a


OK,就是这样!这就是用原生模拟 Observable 的实现过程!

撰文不易,点赞鼓励👍👍👍👍👍👍

我是掘金安东尼,公众号同名,日拱一卒、日掘一金,再会~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-11-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档