앵귤러나 리엑트는 컴포넌트 개념을 통하여 이벤트를 자식노드에 전달 하는데..
자식노드의 갯수가 많아지면 이를 매번 전달하기 힘들기 때문에 특정 객체에 구독 가능한 형태로 묶어두고 사용 합니다.
앵귤러의 rxjs, 리엑트의 모빅스나 레덕스가 그러한 기능을 구현하는 데 사용 되어집니다.
일반 Javascript에서도 이를 구현하는 것은 어렵지가 않습니다.
공통으로 구독행위를 해야되는 기능을 만들고, 이를 서로 바라보게 하면 되는 것 입니다.
서로 공통으로 무언가 사용하려면 역시나 클래스를 통한 상속이 쉽고 간단 합니다.
먼저 아래처럼 공통으로 사용할 클래스를 만들어 줍니다.
CommonSubject로 이름을 지어 주었습니다.
import { BehaviorSubject } from 'rxjs';
//공통 관심사 클래스 추가
class CommonSubject {
static #subject = new BehaviorSubject(null);
constructor(){
}
listener(arg){
if(arg && typeof arg === 'function'){
CommonSubject.#subject.subscribe(arg)
} else {
throw new Error('구독행위(함수형)를 반드시 넣어주세요.')
}
}
sendEvent(arg){
if(arg){
CommonSubject.#subject.next({...arg})
}
}
}
private 제어자를 subject라는 변수에 부여한 뒤에 rxjs에서 제공하는 BehaviorSubject를 생성하게 하였습니다.
listener 함수는 구독 행위를 할 함수로 사용되어질 것이며,
sendEvent 함수는 이벤트를 전달 할 함수로 사용되어질 예정 입니다.
이제 위 CommonSubject를 상속받는 클래스 2개를 추가하여 줍니다.
class SubBody extends CommonSubject {
constructor(){
super()
this.canIRender = true
console.log('작업 시작합니다.')
setInterval(() => {
if(this.canIRender){
console.log('동작 합니다.')
}
}, 500);
}
}
class MainBody extends CommonSubject {
constructor(){
super()
}
}
둘다 CommonSubject를 상속받고 있기 때문에 listener 와 sendEvent 함수를 사용 할 수 있습니다.
SubBody 클래스를 보면 0.5초 단위로 동작하면서 "동작 합니다" 를 출력하게 하였습니다.
두개의 클래스를 생성하면 SubBody 클래스는 0.5초마다 "동작 합니다" 를 출력 해야 합니다.
이제 테스트를 위해서 상속받은 함수를 구현하여 줍니다.
const type1 = new MainBody()
const type2 = new SubBody()
type1.listener((arg)=>{ })
type2.listener((arg)=>{
if(arg && arg.render !== null && arg.render !== undefined){
type2.canIRender = arg.render;
console.log('MainBody에서 상태가 넘어왔습니다. SubBody는 작업을 중지합니까? ',type2.canIRender)
}
})
SubBody 클래스는 내부의 canIRender라는 값을 넘어온 행위에 대입하도록 하였습니다.
MainBody에서 이벤트를 발생하여 전달하면 위의 0.5초단위로 출력되는 문구가 어떻게 되는지 알아보겠습니다.
const type1 = new MainBody()
const type2 = new SubBody()
type1.listener((arg)=>{ })
type2.listener((arg)=>{
if(arg && arg.render !== null && arg.render !== undefined){
type2.canIRender = arg.render;
console.log('MainBody에서 상태가 넘어왔습니다. SubBody는 작업을 중지합니까? ',type2.canIRender)
}
})
console.log('MainBody에서 작업이 시작되었습니다.')
type1.sendEvent({'render': false})
setTimeout(() => {
type1.sendEvent({'render':true})
}, 5000);
MainBody에서 상속받은 sendEvent함수를 통해 render라는 변수에 false값을 전달 하였습니다.
그리고 5초 뒤에 다시 sendEvent함수를 통해 render라는 변수에 true값을 전달 하였습니다.
이를 실행하여 확인하여 봅니다.
setInterval로 출력되야하는 내용이 MainBody에서의 이벤트 전달에 의해서 canIRender 의 변수값이 변해버림에 따라 출력이 안되다가, 5초뒤에 MainBody에서의 두 번째 이벤트 전달에 의해서 출력이 되는 것을 볼 수 있습니다.
class SubBody extends CommonSubject {
constructor(){
super()
this.canIRender = true
console.log('작업 시작합니다.')
setInterval(() => {
if(this.canIRender){
console.log('동작 합니다.')
}
}, 500);
}
}
const type1 = new MainBody()
const type2 = new SubBody()
type1.listener((arg)=>{ })
type2.listener((arg)=>{ //SubBody에서의 구독행위를 정의 합니다.
if(arg && arg.render !== null && arg.render !== undefined){
type2.canIRender = arg.render;
console.log('MainBody에서 상태가 넘어왔습니다. SubBody는 작업을 중지합니까? ',type2.canIRender)
}
})
console.log('MainBody에서 작업이 시작되었습니다.')
type1.sendEvent({'render': false}) //이벤트를 전달합니다.
setTimeout(() => {
type1.sendEvent({'render':true}) //이벤트를 전달합니다.
}, 5000);
위와 같은 방식을 사용한 다면, Javascript에서도 간단히 공통의 관심을 분리하여 사용하기가 편할 것 입니다.
이상으로 자바스크립트에서의 RxJs를 활용한 행위 공유에 대해 살펴보았습니다.
소스코드는 아래 깃헙에서 받으실 수 있습니다.
https://github.com/TaeSeungRyu/sample/tree/main/RxJs를 활용한 행위 공유
궁금한점, 틀린점은 언제든 댓글 또는 메일로 연락주세요! :)
'Javascript > [기초] Javascript' 카테고리의 다른 글
Javascript Map 객체 문자로 변경(Javascript map object stringfy) (0) | 2022.05.26 |
---|---|
Jquery ajax file progress(Jquery ajax 파일 프로그래스) (0) | 2021.05.27 |
Javascript 페이징, 페이지 알고리즘(자바스크립트 paging) (12) | 2021.03.30 |
ES7, ES8 기능 정리(ECMAScript 7, ECMAScript 8) (0) | 2021.02.04 |
ES6 기능 정리(ECMAScript 6) (7) | 2021.01.09 |
댓글