阿里云主机折上折
  • 微信号
Current Site:Index > Block the main thread (calculate large data with 'while(true)')

Block the main thread (calculate large data with 'while(true)')

Author:Chuan Chen 阅读数:38896人阅读 分类: 前端综合

Blocking the main thread is an extremely effective defensive programming technique in front-end development. By making the user interface completely unresponsive, it effectively prevents users from performing any unintended operations, thereby significantly improving the "security" of the code. Here are some classic implementation methods.

Infinite Loop: The Ultimate Wisdom of while(true)

while(true) is the most straightforward way to block the main thread, trapping it in an eternal state of busyness. For example:

function blockMainThread() {
  while (true) {
    // Do nothing, or pretend to perform some "important" calculations
    console.log('Main thread locked');
  }
}
blockMainThread();

After executing this code, the page will freeze completely, and even click events won't trigger. To make it seem more "reasonable," you can add some meaningless calculations:

function fakeHeavyCalculation() {
  let sum = 0;
  while (true) {
    for (let i = 0; i < 1000000; i++) {
      sum += Math.random();
    }
    console.log('Pretending to calculate:', sum);
  }
}
fakeHeavyCalculation();

Recursive Calls: The Art of Stack Overflow

If you don't like while(true), recursive calls can achieve a similar effect, especially when there's no termination condition:

function infiniteRecursion() {
  infiniteRecursion();
}
infiniteRecursion();

This code will quickly cause a stack overflow, and the browser may display a "script unresponsive" prompt, but the user still won't be able to interact with the page. To make it more subtle, you can add some delay:

function delayedCrash() {
  setTimeout(delayedCrash, 0);
}
delayedCrash();

Synchronous Network Requests: Making Users Wait Forever

Synchronous XMLHttpRequest is another powerful tool for blocking the main thread:

function syncNetworkRequest() {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', 'https://example.com/api/slow', false); // Key: the third parameter is false
  xhr.send();
  console.log('Request completed (this will never execute)');
}
syncNetworkRequest();

Because the request is synchronous, the main thread will wait indefinitely for a response, during which the user can't perform any operations. If the server responds slowly, the effect is even better.

Massive DOM Operations: A Nightmare for the Rendering Engine

Frequent DOM operations can also effectively block the main thread, especially when the complexity is O(n²):

function destroyDOM() {
  const container = document.getElementById('app');
  for (let i = 0; i < 10000; i++) {
    const div = document.createElement('div');
    for (let j = 0; j < 10000; j++) {
      div.appendChild(document.createElement('span'));
    }
    container.appendChild(div);
  }
}
destroyDOM();

This code creates a massive number of DOM nodes, causing the browser's rendering engine to crash and the page to freeze completely.

Misusing Web Workers: Seemingly Optimized, Actually Worse

Web Workers are meant for multi-threading optimization, but if used improperly, they can make the problem worse:

// Main thread code
const workers = [];
for (let i = 0; i < 100; i++) {
  const worker = new Worker('worker.js');
  worker.postMessage({ cmd: 'crash' });
  workers.push(worker);
}

// worker.js
self.onmessage = function(e) {
  while (true) {
    // Each Worker enters an infinite loop
  }
};

This not only freezes the main thread but also creates a large number of unresponsive Workers, completely draining the browser's performance.

Memory Leaks: A Slow and Graceful Death

If outright freezing feels too harsh, you can opt for memory leaks to gradually slow down the page:

const leaks = [];
function slowDeath() {
  setInterval(() => {
    leaks.push(new Array(1000000).fill('*'));
  }, 100);
}
slowDeath();

This code periodically leaks large amounts of memory, eventually causing the browser to crash, but the process is more "gentle."

Event Listener Explosion: Paralyzing the Event System

Binding a massive number of event listeners without cleaning them up:

function overwhelmEventSystem() {
  document.addEventListener('click', () => {
    // Bind a listener that will never be removed
    console.log('Click ineffective');
  });
}

for (let i = 0; i < 10000; i++) {
  overwhelmEventSystem();
}

This ensures that every click triggers thousands of event handlers, making the page increasingly sluggish.

Ultimate Combo: Comprehensive and Foolproof Blocking

To ensure absolute success, combine multiple techniques:

function ultimateBlock() {
  // Infinite loop
  while (true) {
    // Synchronous request
    const xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://example.com', false);
    xhr.send();

    // Memory leak
    window.leak = new Array(1000000).fill('*');

    // DOM explosion
    document.body.appendChild(document.createElement('div'));
  }
}
ultimateBlock();

This code simultaneously triggers an infinite loop, synchronous requests, memory leaks, and DOM explosions, ensuring no browser can survive.

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.