首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >随笔:实现一个事件循环

随笔:实现一个事件循环

作者头像
theanarkh
发布2022-03-30 20:02:58
发布2022-03-30 20:02:58
6320
举报
文章被收录于专栏:原创分享原创分享
代码语言:javascript
复制
class EventSystem {

  constructor() {
    // 任务队列
    this.queue = [];
    // 是否需要停止任务队列
    this.stop = 0;
    // 唤醒函数
    this.wakeup = null;
  }

  // 没有任务时,事件循环的睡眠时间
  wait() {
    return new Promise((resolve) => {
      // 记录resolve,可能在睡眠期间有任务到来,则需要提前唤醒
      this.wakeup = () => {
        this.wakeup = null;
        resolve();
      };
    });
  }

  // 停止事件循环
  setStop() {
    this.stop = 1;
    this.wakeup && this.wakeup();
  }

  // 追加任务
  enQueue(func) {
    this.queue.push(func);
    this.wakeup && this.wakeup();
  }

    // 处理任务
    async handleTask() {
        if (this.queue.length === 0) {
            return;
        }
        // 本轮事件循环加入到任务,下一轮事件循环再处理,防止其他任务没有机会处理
        const queue = this.queue;
        this.queue = [];
        while(queue.length) {
            const func = queue.shift();
            await func();
        }
    }

  // 事件循环
  async run() {
        // 如果设置了 stop 标记则退出事件循环
    while(this.stop === 0) {
            // 处理任务,可能没有任务需要处理
            await this.handleTask();
            // 处理任务过程中如果设置了 stop 标记则退出事件循环
            if (this.stop === 1) {
                break;
            }
       // 没有任务了,进入睡眠
       if (this.queue.length === 0) {
                await this.wait();
            }
    }
        // 退出前可能还有任务没处理,处理完再退出
        this.handleTask();
  }
}

// 新建一个事件循环系统
const eventSystem = new EventSystem();

// 生产任务
eventSystem.enQueue(() => {
  console.log('hi');
});
eventSystem.enQueue(() => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('execute after 3s');
      resolve();
    }, 3000);
  });
});
// 模拟定时生成一个任务
setTimeout(() => {
  eventSystem.enQueue(() => {
    console.log('hello');
        eventSystem.setStop();
  });
}, 1000);

// 启动事件循环
eventSystem.run();

之前写了个简单的事件循环的实现,最近优化了下,事件循环的原理很简单,但是需要处理的细节其实还是不少。事件循环本质是个生产者 / 消费者的模式, 核心之一就是生产者 / 消费者同步的问题,也就是没有任务处理时,消费者如何实现阻塞,有任务时,生产者如何唤醒消费者,比如在 Node.js 里通过事件驱动模块来实现,线程池则通过条件变量来实现,而这里通过 Promise 实现。

通过 100 行代码我们就可以大致了解通常说的事件循环,虽然简单,但是大多数现代的高性能服务器都是基于这种模式,比如 Node.js、Nginx、Redis。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程杂技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档