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

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

image.png

本篇译自:javascript.plainenglish.io/how-to-use-…


接上两篇:


我们认识了 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

let Subscription = function(handlerId, unsubscribeNotificationCallback) {
  let self = this;
  self.unsubscribe = () => {
    if(unsubscribeNotificationCallback) {
      unsubscribeNotificationCallback(handlerId);
    }
  };
  return self;
};


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


再看 Subject 完整代码实现:

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 实现:


.
.
.
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 实现:

.
.
.
const dashboardServiceSubscription = myDashboardService.data.subscribe((data) => {
  ...
});
.
.
.
dashboardServiceSubscription.unsubscribe();
.
.
.


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


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

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


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

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


相关文章
|
27天前
|
消息中间件 数据库
开发指南062-异步处理接口
后台有些接口耗时非常长,如果采用同步处理机制,前台等待时间过长,这时需要改异步操作
|
6月前
|
Java 开发者 UED
Java 异步和事件驱动编程:探索响应式模式
【4月更文挑战第27天】在现代软件开发中,异步和事件驱动编程是提高应用性能和响应性的关键策略。Java 提供了多种机制来支持这些编程模式,使开发者能够构建高效、可扩展的应用程序。
121 4
|
6月前
|
前端开发 JavaScript
js开发中的异步处理
JavaScript中的异步处理包括回调函数、Promise和async/await。回调函数是早期方法,将函数作为参数传递给异步操作并在完成后执行。Promise提供链式处理,通过resolve和reject管理异步操作的成功或失败。async/await基于Promise,允许写更简洁的同步风格代码,通过try-catch处理错误。Promise和async/await是现代推荐的异步处理方式。
|
6月前
|
JavaScript 前端开发
揭秘 `nextTick`:解决异步回调的利器(上)
揭秘 `nextTick`:解决异步回调的利器(上)
揭秘 `nextTick`:解决异步回调的利器(上)
|
6月前
|
JavaScript 前端开发
揭秘 `nextTick`:解决异步回调的利器(下)
揭秘 `nextTick`:解决异步回调的利器(下)
揭秘 `nextTick`:解决异步回调的利器(下)
|
前端开发 JavaScript API
RxJS系列01:响应式编程与异步
RxJS系列01:响应式编程与异步
198 0
|
前端开发 JavaScript API
继续解惑,异步处理 —— RxJS Observable
Observable 可观察对象是开辟一个连续的通信通道给观察者 Observer,彼此之前形成一种关系,而这种关系需要由 Subscription 来确立,而在整个通道中允许对数据进行转换我们称为操作符 Operator。
探秘 RxJS Observable 为什么要长成这个样子?!
我们都知道 RxJS Observable 最基础的使用方法:是建立 Observable,即调用 .create API
|
前端开发 JavaScript Java
前端异步(async)解决方案(所有方案)(三)
前端异步(async)解决方案(所有方案)
329 0
前端异步(async)解决方案(所有方案)(三)
|
IDE 开发工具 Android开发
使用rxjava创建一个rxbus事件处理框架
RxJava已经出现很多个年头了,但是依然被很多公司使用,如果现在还对RxJava了解的不够透彻, 可以看这个系列对它的分析:相信看完后你对它会有个更全面的认识。 这个系列主要从下面几个方面来讲解: **RxJava基本操作符使用** **RxJava响应式编程是如何实现的** **RxJava的背压机制及Flowable是如何实现背压的** **RxJava的线程切换原理