前端入栈和出栈

在编程中,事件入栈(Event Pushing)和出栈(Event Popping)通常与事件循环(Event Loop)和消息队列(Message Queue)相关。这些概念在前端开发中尤其重要,特别是在处理异步事件和回调函数时。下面我将解释这些概念,并提供一些代码示例。

事件循环(Event Loop)

事件循环是JavaScript运行时环境的一部分,它负责协调事件、用户交互、脚本执行、渲染、网络请求等。JavaScript是单线程语言,事件循环使得它能够执行非阻塞操作。

消息队列(Message Queue)

消息队列是一个先进先出(FIFO)的数据结构,用于存储待处理的事件。这些事件可能是用户交互(如点击、滚动等)、定时器超时、网络请求完成等。

事件入栈(Event Pushing)

当一个事件发生时,如用户点击了一个按钮,这个事件会被创建并放入消息队列的末尾。这个过程称为事件入栈。

// 假设这是一个用户点击事件的处理函数
function handleClick() {
  console.log('Button clicked!');
}

// 用户点击按钮时,handleClick事件被放入消息队列
button.addEventListener('click', handleClick);

事件出栈(Event Popping)

事件循环会不断检查消息队列。如果队列非空,并且主线程(当前执行栈)空闲,事件循环会将消息队列中的第一个事件出栈,并执行其回调函数。

// 事件循环的简化示意
while (true) {
  if (messageQueue.isNotEmpty() && mainThread.isIdle()) {
    let event = messageQueue.dequeue(); // 出栈
    event.callback(); // 执行回调
  }
}

示例

下面是一个简单的例子,演示了定时器事件如何入栈和出栈:

console.log('Script start');

setTimeout(function timeoutCallback() {
  console.log('Timeout occurred');
}, 0);

console.log('Script end');

// 输出顺序:
// Script start
// Script end
// Timeout occurred

在这个例子中,即使setTimeout的延迟时间设置为0,回调函数timeoutCallback也不会立即执行。首先,当前的执行栈(同步代码)必须完成执行,即打印"Script start"和"Script end"。然后,事件循环会从消息队列中取出定时器事件,并执行其回调函数,打印"Timeout occurred"。

希望这些解释和示例能帮助你理解事件入栈和出栈的概念。

实战:

export const stack:any = []

export function executeFunctionFromString(functionString?:string, args?: any[]) {
  if (functionString) {
    if ((window as any).log) {
      try {
        var fn = eval("(" + functionString + ")");
        fn(...(args || []));
      } catch (error) {
      }
    } else {
      stack.push(function() {
        var fn = eval("(" + functionString + ")");
        fn(...(args || []));
      });

      function executeStack() {
        if (stack.length > 0) {
          setTimeout(function() {
            if ((window as any).log) {
              // 出栈并执行
              let fn = stack.pop();
              fn();
            } else {
              executeStack()
            }
          }, 1000);
       }
      }
      executeStack()
    }
  }
} 

这个场景是需要通过npm传递函数,所以把函数转换成字符串,接受后再转换成函数。但出现一个问题,就是执行的需要依赖log,但是log又需要出示化后才能用,所以就把事件入栈,等1秒后在执行,如果有log就执行然后事件出栈,没有的话在等1秒后执行。

posted @ 2023-11-29 17:34  井凉一一  阅读(19)  评论(0编辑  收藏  举报