EventTarget 인터페이스 사용

.NET에서 CustomEvent 인터페이스를 사용하는 방법을 배웠습니다.

브라우저와 터미널(Node.js 사용) 모두에 대해 동일한 JavaScript 코드를 사용하여 진행률 표시기를 어떻게 만들 수 있습니까? 이를 위해 두 환경 모두와 호환되는 CustomEvent 인터페이스를 사용하여 진행률 이벤트가 있는 래퍼fetch를 빌드할 수 있습니다.

📣 CustomEvent 인터페이스는 실험적 API로 Node.jsv18.7.0에 추가되었으며, global 플래그를 사용하여 --experimental-global-customevent 에 노출됩니다.

이벤트 구현



클라이언트가 이벤트를 구독할 수 있도록 사용자 정의 클래스에서 이벤트를 전달하도록 EventTarget 인터페이스를 확장해야 합니다.

class Http extends EventTarget {
  

  async get(url) {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(response.statusText);
    }
    const contentLength = this._getContentLength(response);
    const self = this;
    const res = new Response(new ReadableStream({
      async start(controller) {
        const reader = response.body.getReader();
        let loaded = 0;
        try {
          while (true) {
            const {done, value} = await reader.read();
            if (done) {
              break;
            }
            loaded += value.byteLength;
            if (contentLength) {
              self.dispatchEvent(new CustomEvent('progress', {detail: {contentLength, loaded}}));
            }
            controller.enqueue(value);
          }
          controller.close();
        } catch (err) {
          controller.error(err);
        }
      }
    }));
    return res.blob();
  }
}

export default Http;

ReadableStream 속성의 body 인스턴스를 사용자 지정 구현으로 래핑하여 progress 이벤트의 수신기에 읽기 진행률을 알렸습니다. 또한 read() 플래그가 스트림 끝에 도달했음을 나타낼 때까지 응답의 모든 콘텐츠를 done 처리해야 합니다.



터미널에서 진행 이벤트 사용


Http 클래스를 가져오고 progress 이벤트에 대한 이벤트 리스너를 추가해 보겠습니다. 이 예에서는 다운로드 속도가 최대 30kbps인 서버를 사용합니다.

const exec = async () => {
  const { default: Http } = await import('./http.mjs');

  const http = new Http();
  const listener = e => console.log(e.detail);
  http.addEventListener('progress', listener);
  await http.get('https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg');
  http.removeEventListener('progress', listener);
}

exec();


💡 서버의 메모리 누수를 방지하려면 리스너를 제거해야 합니다. 😉

🧠 ES 모듈을 CommonJS 코드로 가져오려면 동적import()을 사용해야 합니다.

이 코드를 실행하려면 --experimental-global-customevent 플래그를 포함해야 합니다. 그렇지 않으면 CustomEvent 클래스는 undefined 가 됩니다.

node --experimental-global-customevent index.js


브라우저에서 진행 이벤트 사용


index.html를 만들고 다음 코드를 사용하여 JavaScript 모듈을 가져오겠습니다.

<script type="module">
  import Http from './http.mjs';

  const http = new Http();
  const listener = e => console.log(e.detail);
  http.addEventListener('progress', listener);
  await http.get('https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg');
  http.removeEventListener('progress', listener);
</script>


다음 명령을 사용하여 예제를 로컬에서 실행할 수 있습니다.

npx http-server


이제 http://localhost:8080로 이동하여 콘솔 출력을 확인할 수 있습니다.

결론


EventTarget 인터페이스를 사용하면 HTML 요소 또는 터미널에 연결하여 사용자에게 진행 상황을 알릴 수 있는 UI에서 분리된 재사용 가능한 코드를 생성할 수 있습니다.

서버의 플래그 뒤에 실험적 API를 사용하지 않으려면 Node.js에서 EventEmitter 클래스를 사용할 수 있습니다.



https://github.com/navarroaxel/fetch-progress에서 전체 코드 예제를 확인할 수 있습니다.

이 게시물에서는 https://github.com/AnthumChris/fetch-progress-indicatorsfetch-basic 예제를 .

오픈 소스 바위. 🤘

좋은 웹페이지 즐겨찾기