Javascript

Queue์œผ๋กœ ์ž‘์—…์‹คํ–‰

frontChoi 2025. 5. 19. 08:06
๋ฐ˜์‘ํ˜•

๐Ÿ’ Task ๋ฅผ Queue๋ฅผ ์ด์šฉํ•˜์—ฌ ์ž‘์—… ์ฒ˜๋ฆฌ ํ•˜๊ธฐ

ํšŒ์‚ฌ์—์„œ ์ž‘์—…์„ ํ•˜๋˜ ๋„์ค‘ ํ•ด๋‹น์‹œ๊ฐ„์ด ๋˜๋ฉด Queue์— ๋‹ด๊ธด ์ˆœ์„œ๋Œ€๋กœ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค.

๋กœ์ง์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค

  1. A์Œ์› ์‹คํ–‰
  2. ํŠน์ •์‹œ๊ฐ„์ด ๋˜๋ฉด B ์Œ์› ์‹œ์ž‘
  3. B์Œ์›์ด ๋๋‚˜๋ฉด C์Œ์› ์‹œ์ž‘
  4. C์Œ์› ๋๋‚˜๋ฉด D์Œ์› ์‹œ์ž‘
  5. D์Œ์› ๋๋‚˜๋ฉด ๋‹ค์‹œ A์Œ์› ์‹œ์ž‘

๋‹จ 2~4๋Š” A์Œ์›์ด ์Œ์†Œ๊ฑฐ๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค

 

 

 

 

๐Ÿคฟ TaskQueue ํด๋ž˜์Šค ์ž‘์„ฑ

class TaskQueue {
  constructor() {
    this.queue = [];
    this.isRunning = false;
  }

  add(task) {
    this.queue.push(task);
    this.runNext();
  }
  isLast() {
    return this.queue.length === 0;
  }

  async runNext() {
    if (this.isRunning || this.queue.length === 0) return;

    this.isRunning = true;

    const task = this.queue.shift();

    if (task) {
      try {
        await task();
      } catch (error) {
        console.error('์ž‘์—… ์‹คํ–‰ ์ค‘ ์—๋Ÿฌ:', error);
      }
    }

    this.isRunning = false;
    this.runNext();
  }
}

export const taskQueue = new TaskQueue();

 

add ํ•จ์ˆ˜ : Queue์— ์ž‘์—…์„ ๋„ฃ๋Š” ํ•จ์ˆ˜์ด๋ฉฐ, ์ž‘์—…์„ ๋„ฃ๋Š” ์ˆœ๊ฐ„ runNext ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค

runNext ํ•จ์ˆ˜ : ํ˜„์žฌ ๋งจ ์•ž์— ์žˆ๋Š” task๋ฅผ ์ถ”์ถœํ•˜์—ฌ, task๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋‹ค์Œ ์‹คํ–‰ํ•  task๊ฐ€ ์žˆ์œผ๋ฉด ์‹คํ–‰ํ•˜๊ณ  ์•„๋‹ˆ๋ฉด ์ข…๋ฃŒํ•œ๋‹ค

 

โšฝ๏ธ TaskQueue๋ฅผ ์ด์šฉํ•˜์—ฌ ์ž‘์—… ๋‹ด๊ธฐ

taskQueue์— ์ž‘์—…์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค

  • FadeOut
  • B์Œ์› ์‹œ์ž‘(B์Œ์›์ด ๋๋‚˜๋ฉด C,D์Œ์›์ด ์‹œ์ž‘๋œ๋‹ค)

TaskQueue์˜ addํ•จ์ˆ˜์— ๋‹ด๊ธฐ

์ฒซ๋ฒˆ์งธ๋กœ TaskQueue์— fadeOut, playVideo ํ•จ์ˆ˜๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰์‹œํ‚จ๋‹ค

import { taskQueue } from './utils/taskQueue';
// ๊ฐ€์งœ API
 dummyVideoList().then(res => {
    if (Array.isArray(res)) {
      res.forEach((item, index) => {
        const { id, url } = item;
        /* Task Add๋ฅผ ํ†ตํ•˜์—ฌ ํ•จ์ˆ˜ ๋‹ด๊ธฐ */
        taskQueue.add(async () => {
          await fadeOut(this.$refs.streamingvideo, 5000);
          await this.playVideo(url);
        });
      });
    }
  });

 

TaskQueue์˜ add ํ•จ์ˆ˜์— ๋‹ด๊ธฐ๋ฉด, runNext ์‹คํ–‰

addํ•จ์ˆ˜์— ๋‹ด๊ธฐ๋ฉด, runNext์—์„œ queue์˜ ๋งจ์•ž์˜ ์ž‘์—…์„ ์ถ”์ถœํ•˜์—ฌ ์‹คํ–‰ํ•œ๋‹ค

 

add(task) {
  this.queue.push(task);
  this.runNext();
}

/* TaskQueue ํด๋ž˜์Šค์˜ runNext ํ•จ์ˆ˜ */
async runNext() {
    if (this.isRunning || this.queue.length === 0) return;

    this.isRunning = true;
	/* 
    queue์˜ ๋งจ์•ž ์ž‘์—…์„ ์ถ”์ถœํ•œ๋‹ค. 
    ์ถ”์ถœํ•˜๋Š” ํ•จ์ˆ˜๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค
    async () => {
          await fadeOut(this.$refs.streamingvideo, 5000);
          await this.playVideo(url);
        } 
    */
    const task = this.queue.shift();

    if (task) {
      try {
        await task();
      } catch (error) {
        console.error('์ž‘์—… ์‹คํ–‰ ์ค‘ ์—๋Ÿฌ:', error);
      }
    }

    this.isRunning = false;
    this.runNext();
  }

 

 

playVideo๋ฅผ ์‹คํ–‰์‹œํ‚จํ›„ ๋‹ค์Œ Task๋ฅผ ์–ด๋–ป๊ฒŒ ํŠธ๋ฆฌ๊ฑฐ์‹œํ‚ฌ๊ฒƒ์ธ๊ฐ€

์—ฌ๊ธฐ์„œ playVideo์— ํ•จ์ˆ˜์— ๋Œ€ํ•œ ์„ค๋ช…์„ ์ ์ง€ ์•Š์•˜๋Š”๋ฐ, playVideo๊ฐ™์€ ๊ฒฝ์šฐ video ํƒœ๊ทธ์— url์„ ์„ธํŒ…ํ•˜๊ณ  video playํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ playVideo๊ฐ€ Promise๋กœ ๊ด€๋ฆฌ๋˜์–ด ์žˆ๋‹ค. Promise์—์„œ๋Š” resolveํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Promise๊ฐ€ ์ข…๋ฃŒ๊ฐ€ ๋œ๋‹ค

๊ทธ๋ฆฌํ•˜์—ฌ resolve๋ฅผ ์™ธ๋ถ€ ๋ณ€์ˆ˜์ธ this.currentResolve์— ๋‹ด๋Š”๋‹ค

playVideo(src) {
  return new Promise(resolve => {
    const video = this.$refs.videoPlayer;
    // resolve ํ•จ์ˆ˜ ๋‹ด๊ธฐ
    this.currentResolve = resolve;

    video.src = src;
    video.load();
    video.play();
  });
},

 

๊ทธ๋ฆฌ๊ณ  ๋น„๋””์˜ค endEvent์—์„œ ์™ธ๋ถ€๋ณ€์ˆ˜์ธ currentResolve๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค

onVideoEnded() {
  if (this.currentResolve) {
    this.currentResolve(); // ํ˜„์žฌ ๋น„๋””์˜ค ๋๋‚˜๋ฉด ํ ๋‹ค์Œ ์ž‘์—… ์‹คํ–‰
    this.currentResolve = null;
    if (taskQueue.isLast()) {
      fadeIn(this.$refs.streamingvideo, 5000, 1);
    }
  }
},

 

๋น„๋””์˜ค endEvent์—์„œ ์™ธ๋ถ€๋ณ€์ˆ˜์ธ currentResolve๋ฅผ ์‹คํ–‰์‹œํ‚ค๋ฉด

1. fadeOut ํ•จ์ˆ˜ ์‹คํ–‰

2. playVideo ํ•จ์ˆ˜ ์‹คํ–‰, ์—ฌ๊ธฐ์„œ resolve๋ฅผ ์™ธ๋ถ€ ๋ณ€์ˆ˜์ธ currentResolve์— ๋‹ด๊ธฐ

3. video EndEvent์—์„œ currentResolve ํ•จ์ˆ˜ ์‹คํ–‰

4. taskํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉฐ, ๋‹ค์Œ ์ค„ ์‹คํ–‰(๋‹ค์Œ task๊ฐ€ ์žˆ์œผ๋ฉด 1~3๋ฐ˜๋ณต)

add(task) {
  this.queue.push(task);
  this.runNext();
}

/* TaskQueue ํด๋ž˜์Šค์˜ runNext ํ•จ์ˆ˜ */
async runNext() {
    if (this.isRunning || this.queue.length === 0) return;

    this.isRunning = true;
	
    const task = this.queue.shift();

    if (task) {
      try {
        /* 
            1. fadeOut ์‹คํ–‰
            2. playVideo ์‹คํ–‰
            3. video endevent์—์„œ playVideo์˜ resolveํ•จ์ˆ˜ ์‹คํ–‰
            async () => {
                  await fadeOut(this.$refs.streamingvideo, 5000);
                  await this.playVideo(url);
                } 
            */
        await task();
      } catch (error) {
        console.error('์ž‘์—… ์‹คํ–‰ ์ค‘ ์—๋Ÿฌ:', error);
      }
    }
    // 4. ๋‹ค์Œ ์ค„ ์‹คํ–‰
    this.isRunning = false;
    this.runNext();
  }

 

 

ํ›„๊ธฐ

์œ„์™€๊ฐ™์ด Task๋ฅผ Queue๋กœ ์ž‘์—…ํ•˜์˜€๋Š”๋ฐ, ๋‹ค๋งŒ ์™ธ๋ถ€๋ณ€์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•ด์•ผํ•˜๋Š” ์•ฝ๊ฐ„์˜ ๋ฌธ์ œ๊ฐ€ ์žˆ์ง€๋งŒ,

Queue๋ฅผ ์ด์šฉํ•˜๋‹ˆ ๋™์‹œ๋‹ค๋ฐœ์  Task๊ฐ€ ์ž‘์—…์ด ๋ฐœ์ƒํ• ๋•Œ, ๊ด€๋ฆฌ๊ฐ€ ์šฉ์ดํ–ˆ๋‹ค

๋ฐ˜์‘ํ˜•