Typescript를 위한 입력된 이벤트 시스템

현재 분산 서비스를 사용하여 pet project 작업을 하고 있습니다.

개발하는 동안 저는 일반적으로 다음과 같이 빠르게 작성되는 고전적인 온/오프 스타일 이벤트 시스템이 필요했습니다.
몇 줄의 코드. 그러나 이번에는 전체 이벤트 시스템 유형을 보호할 수 있는지 궁금했습니다.
Typescript 유형으로.

코드 받기



전체 58줄의 코드를 a github gist에 저장했습니다. 코드가 도용될 경우 책임지지 않음을 알려드립니다.
의도한 대로 작동하지 않거나 어딘가에서 오류가 발생합니다. 자신의 책임하에 사용하십시오.

사용 방법



켜기/끄기 스타일 이벤트 이미터로 작업한 적이 있다면 이 시스템의 사용법은 간단할 것입니다. 나는 여전히 가고있다
간단히 설명하기 위해.

기본 온/오프 스타일 이벤트 시스템 작동 방식



이에 대해 이미 알고 있다면 다음 헤드라인으로 건너뛸 수 있습니다. :)

이벤트 시스템의 경우 일반적으로 코드에 이벤트를 트리거하지 않고 이벤트 발생을 브로드캐스트하는 지점이 있습니다.
누군가가 실제로 듣고 있는지 알고 있습니다.

코드의 다른 부분은 기존 이벤트를 구독하고 이에 반응할 수 있습니다. 웹사이트의 DOM에서 이벤트로 작업한 적이 있다면
정확히 이 패턴:

// Adding a callback function to "change" events on a text box.
// The callback is called every time when a change event happens.
document.getElementById("myCoolTextbox").addEventListener("change", function(event){
    // ...
});


따라서 일부 이벤트에 대한 무한 구독자(리스너)가 있을 수 있으며 이벤트가 트리거될 때마다 모든 구독자에게 알림이 전송됩니다.

이벤트 유형 준비



모든 기존 이벤트와 해당 데이터 페이로드를 정의하는 TypeScriptinterface를 생성할 수 있도록 이벤트 시스템을 설계했습니다.

예를 들어 이벤트 시스템이 있는 가상의 비디오 플레이어 앱을 만들고 싶다면 다음 이벤트를 정의할 수 있습니다.

interface AppEvents {
    load: {
      filename: string;
      format: string;
      totalTimeMs: number;
    },
    update: {
        currentTimeMs: number;
    },
    play: void,
    pause: void,
    stop: void
}


따라서 사용자가 파일을 열 때 load 이벤트, 파일을 재생하는 동안 계속해서 발생하는 update 이벤트가 있습니다.
play , pausestop 이벤트는 사용자 상호 작용 시 트리거됩니다.

이벤트 시스템 생성 및 사용



시스템의 모든 이벤트를 정의하는 TypeScript 인터페이스를 사용하여 실제로 코드로 시스템을 생성할 수 있습니다.

// appEvents.ts
import createEventSystem from "./eventSystem.ts";

interface AppEvents {
    load: {
        filename: string;
        format: string;
        totalTimeMs: number;
    },
    update: {
        currentTimeMs: number;
    },
    play: void,
    pause: void,
    stop: void
}

const eventSystem = createEventSystem<AppEvents>();
export default eventSystem;


이제 시스템은 우리 코드의 어디에서나 사용할 수 있습니다. Typescript는 알려진 이벤트만 트리거되도록 합니다.
예상 페이로드를 정확히 수신해야 합니다.

import appEvents from "./appEvents.ts";
import { loadAndParseAudioFile } from "./audioLoader.ts";

export async function loadFile(filename){
    const {
        filename,
        format,
        totalTimeMs
    } = await loadAndParseAudioFile(filename);

    appEvents.trigger("load", {filename, format, totalTimeMs});
}


애플리케이션의 다른 부분에서 코드는 정의된 이벤트를 구독할 수 있습니다.

// logger.ts
import appEvents from "./appEvents.ts";

appEvents.on("load", (payload) => {
    console.log(`You opened the file ${payload.filename} with a length of ${payload.totalTimeMs} milliseconds.`);
});


이벤트 듣기 중지



이벤트 수신에서 분리하려면 .off() 메서드를 호출하고 정확히 동일한 콜백 함수를
오프 핸들러:

function handler(data){
    console.log("An update happened!", data);
}

eventSystem.on("update", handler);

// And somewhere else:
eventSystem.off("update", handler);


유사한 코드를 가진 다른 콜백 함수가 아니라 동일한 콜백 함수여야 한다는 점에 유의하십시오.

이것은 작동하지 않습니다!




eventSystem.on("update", (data) => {
    console.log("An update happened!", data);
});

eventSystem.off("update", (data) => {
    console.log("An update happened!", data);
});

// These are TWO separate functions, therefore the "off" call did not work.


ENUM을 이벤트 이름으로 사용



타입스크립트 인터페이스는 필드 이름의 형식에 신경쓰지 않기 때문에 ENUM을 자유롭게 정의하여
IDE에서 더 쉽게 검색할 수 있도록 기존 이벤트 이름:

export enum EventNames {
    LOAD,
    UPDATE,
    PLAY,
    PAUSE,
    STOP
};

interface AppEvents {
    [EventNames.LOAD]: {
        filename: string;
        format: string;
        totalTimeMs: number;
    },
    [EventNames.UPDATE]: {
        currentTimeMs: number;
    },
    [EventNames.PLAY]: void,
    [EventNames.PAUSE]: void,
    [EventNames.STOP]: void
}


이렇게 하면 다음과 같이 트리거 및 구독을 호출할 수 있습니다.

eventSystem.trigger(EventNames.PLAY);

eventSystem.on(EventNames.UPDATE, ({currentTime}) => {
    console.log(`Current time: ${currentTime}`);
});

-------------

This post was published on my [personal blog](https://parastudios.de/), first. 

You should follow me on dev.to for more tips like this. Click the follow button in the sidebar! 🚀

좋은 웹페이지 즐겨찾기