Web Workers 를 공부하다 SharedWorker 는 각 스크립트들이 MessagePort 를 통해 데이터 전달을 한다는 것을 알게 되었고 관련하여 공부를 하게 됨

MessagePort 는 MessageChannel 간에 데이터를 전달하고 받을 수 있도록 하는 두 개의 ports 중 한 개를 나타냄.

MessageChannel 생성후 channel.port1channel.port2 를 통해 데이터를 전달하고 받을 수 있음

// main.js
const channel = new MessageChannel();

iframe.addEventListener("load", onLoad);
function onLoad() {
  channel.port1.onmessage = function(e) { 
  }

  iframe.contentWindow.postMessage("Hello", "*", [channel.port2]);
}

// iframe.html
<script>
  window.addEventListener('message', onMessage);
  function onMessage(e) {
    e.ports[0].postMessage('Message Back');
  }
</script>

postMessage() 함수의 세번째 인자 transfer 를 사용하면 객체의 소유권을 수신측에 전달함. 송신 측에서는 더 이상 사용 불가능

function onLoad() { 
  channel.port1.onmessage = function(e) {  
  } 
  iframe.contentWindow.postMessage("Hello One", "*", [channel.port2]);
  iframe.contentWindow.postMessage("Hello Two", "*", [channel.port2]); // Uncaught DOMException: Failed to execute 'postMessage' on 'Window': Port at index 0 is already neutered.
}

'IT > Web' 카테고리의 다른 글

[Web API] Web Workers API  (0) 2022.09.14

스크립트 연산을 주 실행 스레드와 분리된 별도의 백그라운드 스레드에서 실행할 수 있는 기술

종류

  • 전용 워커 - 단일 스크립트에서만 사용하는 워커 : DedicatedWorkerGlobalScope
  • 공유 워커 - 여러 스크립트에서 공유하는 워커 : SharedWorkerGlobalScope
    • SharedWorker
  • 서비스 워커 - 웹 응용 프로그램, 브라우저, 네트워크 사이의 프록시 서버 역할
    • 네트워크 요청 인터셉트
    • 푸시 알람
    • 백그라운드 동기화
  • 오디오 워커 - 직접적인 오디오 처리 능력 제공

제한사항

  1. 워커에서 DOM 직접 조작 불가능
  2. window 의 일부 메소드 사용 불가능
  3. WebSocket 과 IndexedDB 는 사용 가능

데이터 교환

워커와 메인 스레드 간의 데이터 교환은 메세지 시스템 사용 (postMessage, onmessage) 데이터는 복사하고 공유는 하지 않음

Example

!! 워커 생성 시 Worker() 생성자 사용함. 워커 스레드 생성시에는 현재 window 와는 다른 전역 Context 에서 생성해야 동작함
(테스트 위해서 $ npx lite-server 이용했음)


전용워커)

// main.js
if (window.Worker) {
  const myWorker = new Worker("worker.js");
  const payload = {flag: 1}
  myWorker.postMessage(payload);

  myWorker.onmessage = function(e) {
    if (payload.data == e.data) {
      console.log('Never called');
    } else {
      console.log('Always called');
    }
  }
}

// worker.js
onmessage = function(e) {
  console.log(e.data) // {flag: 1}

  e.data.flag = 2;  // 데이터를 공유하지 않기에 main.js 의 payload 객체에 영향을 주지 않음

  postMessage(e.data.flag);
}

공유워커)

// main.js
if (window.SharedWorker) {
  const myWorker = new SharedWorker("worker.js");
  const payload = {flag: 1}
  myWorker.port.postMessage(payload);
  myWorker.port.onmessage = function(e) {
    console.log(e.data);
  }
}

// worker.js
onconnect = function (event) {
  const port = event.ports[0];

  port.onmessage = function(e) {
    port.postMessage('');
  }
}

'IT > Web' 카테고리의 다른 글

[WebAPI] MessagePort  (0) 2022.09.14

+ Recent posts