Code Monkey home page Code Monkey logo

exercise17's Introduction

exercise17's People

Contributors

loskael avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

exercise17's Issues

test.js 断言小概率错误

image

同理

ob.sum = 0;
val = Math.random() * 1e9 >> 0;
subject.removeObserver(ob);
assert.ok(subject.observers.count() === 0);
subject.notify(val);
assert.ok(ob.sum !== val);

这一段中如果 val 随机到了一个0 就算 removeObserver 和 notify 没有问题,的断言assert.ok(ob.sum !== val); 也会失败。

目前对观察订阅者模式的一些体会和应用场景

目前对观察订阅者模式的一些体会和应用场景

1、监听

以前在用vue重构我的项目时,自己写一个类似rxjs的简单版SimpleObservable,用于实现header title等的监听,因为在我的项目中,不同页面的header只有title文字不一样,比如page1显示的titile是'page1',于是我把header做成了一个组件,而每个页面也是一个组件,因此通过SimpleObservable就可以实现组件与组件间的间接单向通信,即观察者(observer)监听被观察者(observable),被观察者触发观察者。

(备注:以下用ts语法,可以通过tsc编译生成对应js,再运行)

大致代码如下:

demo1

SimpleObservable.ts
class SimpleObservable {
  private observer: Array<Function>;
  constructor() {
    this.observer = [];
  }
  subscribe(_observer: Function) {
    this.observer.push(_observer);
    let _index = this.observer.length - 1;
    let that = this;
    return {
      _index: _index,
      unsubscribe: function () {
        console.log("before:unsubscribe:", that.observer);
        that.observer.splice(this._index, 1);
        console.log("after  :unsubscribe:", that.observer);
      }
    };
  }
  next(_data: any) {
    for (let i = 0, len = this.observer.length; i < len; i++) {
      this.observer[i](_data);
    }
  }
}
export default SimpleObservable;
demo1.ts
import SimpleObservable from './SimpleObservable';
let subscriptions=[];
let headerTitleObservable = new SimpleObservable();
let headerTitle_subscriptsion = headerTitleObservable 
      .subscribe(_title => {
        console.log(`the header title is change to${_title }`);
      });
subscriptions.push(headerTitle_subscriptsion );

// 触发
this.headerTitleObservable.next('page1');

// 在组件生命周期结束时,清除所有observers
subscriptions.forEach(subscription => {
      subscription.unsubscribe();
    });

2、解除两个类的强耦合状态

使用观察订阅者模式,有时候能解除两个类的强耦合状态,比如,在我的项目中,我写了一个http拦截器httpInterceptor,用来过滤每一次http请求和响应,比如统一加access_token header,统一出错处理啊等等,我的httpInterceptor其中的一个功能,就是从服务器返回的响应头中检测登录状态是否已经失效或access_token是否已经过期,当检测到登录失效时,要在页面中弹出一个登录modal框(loginModalComponent),提醒用户重新登录。大致的代码如下:

(备注:以下采用ts语法,为了使理解起来更加容易,没有使用ts的依赖注入等特性)

未使用观察者模式:

demo2

demo2.ts
/**
 * 这里模拟了一个登录modal组件
 */
class LoginModalComponent {
  constructor() { }
  open() {
    console.log('##检测到access_token已经过期,打开login模态框##');
    console.log('请输入账号和密码,点击登录');
  }
}

/**
 * 这里模拟了一个http拦截器
 */
class HttpInterceptor {
  loginModalComponent: LoginModalComponent = new LoginModalComponent();;
  constructor() { }
  handleHttpRes() {
    if (this.checkLoginInvalid) {
      this.loginModalComponent.open();
    }
  }
  // 检查登录是否失效
  checkLoginInvalid() {
    return true;
  }
}

let httpInterceptor = new HttpInterceptor();
httpInterceptor.handleHttpRes();

以上示例代码是未使用观察者模式的情况下,需要在HttpInterceptor里new LoginModalComponent,从而导致HttpInterceptor和LoginModalComponent处于强耦合的状态,但是这样不符合HttpInterceptor拦截器的**,因为HttpInterceptor拦截器是不应该和组件相关的东西进行耦合的,因此,采用观察者模式进行改进.

代码如下:

demo3

demo3.ts
class SimpleObservable {
  private observer: Array<Function>;
  constructor() {
    this.observer = [];
  }
  subscribe(_observer: Function) {
    this.observer.push(_observer);
    let _index = this.observer.length - 1;
    let that = this;
    return {
      _index: _index,
      unsubscribe: function () {
        console.log("before:unsubscribe:", that.observer);
        that.observer.splice(this._index, 1);
        console.log("after  :unsubscribe:", that.observer);
      }
    };
  }
  next(_data: any) {
    for (let i = 0, len = this.observer.length; i < len; i++) {
      this.observer[i](_data);
    }
  }
}
/**
 * 这里模拟了一个登录modal组件
 */
class LoginModalComponent {
  constructor() { }
  open() {
    console.log('##检测到access_token已经过期,打开login模态框##');
    console.log('请输入账号和密码,点击登录');
  }
}

/**
 * 通过一个service来作为中间者,从而解除HttpInterceptor和LoginModalComponent强耦合状态。
 */
class HttpStatusService {
  login_invalid_observable = new SimpleObservable();
  constructor() { }
  getLoginInvalidObservable() {
    return this.login_invalid_observable;
  }
  triggerLoginInvalidObservable() {
    this.login_invalid_observable.next('access_token is invalid.')
  }
}

/**
 * 创建一个HttpStatusService的实例,全局可用,实际的做法是采用ts的依赖注入
 */
let httpStatusService: HttpStatusService = new HttpStatusService();
/**
 * 这里模拟了一个http拦截器
 */
class HttpInterceptor {
  constructor() { }
  handleHttpRes() {
    if (this.checkLoginInvalid) {
      httpStatusService.triggerLoginInvalidObservable();
    }
  }
  // 模拟一个登录失败的状态,实际的情况是,拦截到http请求的服务器响应信息
  checkLoginInvalid() {
    return true;
  }
}


/**
 * AppComponent,一个页面跟组件
 */
class AppComponent {
  loginModalComponent: LoginModalComponent = new LoginModalComponent();
  subscriptions: Array<any> = [];
  constructor() {
    this.init();
  }
  init() {
    let subscription1 = httpStatusService.getLoginInvalidObservable().subscribe((err_msg) => {
      this.loginModalComponent.open();
    });
    this.subscriptions.push(subscription1);
  }
  onDestroy() {
    this.subscriptions.forEach(subscription => {
      subscription.unsubscribe();
    });
  }
}

let appComponent = new AppComponent();
/**
 * 此时appComponent已经在监听httpStatusService里的login_invalid_observable
 */
let httpInterceptor = new HttpInterceptor();
httpInterceptor.handleHttpRes();

appComponent.onDestroy();

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.