이벤트 기반으로 프로미스를 만드려고 했는데, IE에 CustomEvent와 EventTarget이 없어서 직접 만들어야 했습니다.
다행히도 둘 다 MDN에 polyfill이 있었습니다. (그런데 지금은 없어요.)
CustomEvent
// myCustomEvent.js
/**
* 커스텀 이벤트 생성자
* @param {string} event
* @param {object} params
* @returns {object} customEvent
*/
var MyCustomEvent = (function setCustomEventConstructor() {
/**
* window.CustomEvent의 constructor를 지원하지 않을 때(IE) CustomEvent() 폴리필을 구현.
* MDN CustomEvent() Polyfill 참고.
* https://developer.mozilla.org/ko/docs/Web/API/CustomEvent/CustomEvent
*/
if (typeof window.CustomEvent !== "function") {
function MyCustomEvent ( event, params ) {
params = params || { bubbles: false, cancelable: false, detail: undefined };
var evt = document.createEvent( 'CustomEvent' );
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
return evt;
}
MyCustomEvent.prototype = window.Event.prototype;
return MyCustomEvent
}
return window.CustomEvent
})()
기본적으로 둘 다 실제 window.CustomEvent나 window.EventTarget이 있으면 그것을 사용하도록 만들었습니다.
간단히 설명하자면,
MyCustomEvent 생성자를 만들고, 그 안에서 createEvent로 이벤트를 만든 후 initCustomEvent로 CustomEvent로 초기화하고 반환합니다.
그리고 MyCustomeEvent의 프로토타입을 Event 프로토타입으로 바꿔줍니다.
현재는 createEvent 대신에 CustomeEvent를 사용하라고 경고하고 있고, initCustomEvent는 아예 완전히 Deprecated 되었습니다.
EventTarget
// customEventTarget.js
/**
* 이벤트 타겟 생성자
* @returns {object} eventTarget
*/
var CustomEventTarget = (function setEventTargetConstructor() {
/**
* window.EventTarget의 constructor를 지원하지 않을 때(IE) EventTarget 폴리필을 구현.
* MDN EventTarget 구현 예제 참고.
* https://developer.mozilla.org/ko/docs/Web/API/EventTarget
*/
if(typeof window.EventTarget !== "function") {
var CustomEventTarget = function() {
this.listeners = {};
};
CustomEventTarget.prototype.listeners = null;
CustomEventTarget.prototype.addEventListener = function(type, callback) {
if (!(type in this.listeners)) {
this.listeners[type] = [];
}
this.listeners[type].push(callback);
};
CustomEventTarget.prototype.removeEventListener = function(type, callback) {
if (!(type in this.listeners)) {
return;
}
var stack = this.listeners[type];
for (var i = 0, l = stack.length; i < l; i++) {
if (stack[i] === callback){
stack.splice(i, 1);
return;
}
}
};
CustomEventTarget.prototype.dispatchEvent = function(event) {
if (!(event.type in this.listeners)) {
return true;
}
var stack = this.listeners[event.type].slice();
for (var i = 0, l = stack.length; i < l; i++) {
stack[i].call(this, event);
}
return !event.defaultPrevented;
};
return CustomEventTarget
}
return window.EventTarget
})()
CustomEventTarget역시 생성자를 만들면서 그안에 이벤트를 저장할 listeners객체를 만들어 둡니다.
CustomEventTarget의 메소드로 addEventListener, removeEventListener, dispatchEvent를 만듭니다.
여기서 이벤트를 listeners객체에 이벤트 이름을 key값으로한 배열에 저장 및 삭제하는 식으로 관리합니다.
그래서 같은 프로미스에 .then이 여러번 호출되더라도 문제없이 동작할 수 있습니다.
→(js)Promise만들기(4) - constructor, resolve, reject
출처: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
출처: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
'WEB > JS' 카테고리의 다른 글
(js)Promise만들기(5) - then, catch (완) (0) | 2024.01.28 |
---|---|
(js)Promise만들기(4) - constructor, resolve, reject (0) | 2024.01.28 |
(js)Promise만들기(2) - 구상 (0) | 2024.01.27 |
(js)Promise만들기(1) - 전체코드 (0) | 2024.01.27 |
(js)마지막 달, 마지막 날 구하기 (0) | 2021.11.05 |