You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于《You Don't Know JS》中Kyle数据分块异步处理的性能与数据交错疑问

Understanding Chunked Async Processing in "You Don't Know JS"

Let me break this down clearly—this pattern solves a critical browser performance problem, but you're right to question the data interleaving issue. Let's unpack both parts:

Why This Improves "Performance"

First, remember that JavaScript runs on a single main thread in browsers. If you tried to process 100,000+ data points all at once, that computation would block the thread for hundreds of milliseconds (or longer). During that time, the browser can't do anything else: no rendering, no handling user clicks/scrolls, no processing other async events. The page would freeze, and users would think it's broken.

This chunked approach fixes that by:

  • Processing only 1000 items at a time (a small enough chunk to avoid blocking the thread for long)
  • Using setTimeout(..., 0) to push the next chunk's processing to the next event loop tick

What setTimeout(0) does is tell the browser: "Finish whatever you're doing right now (like rendering or user input), then come back and run this callback." This lets the browser breathe between processing chunks, keeping the page responsive. The total computation time might be slightly longer, but the user experience is way better—this is what we mean by "improved performance" here (it's about responsiveness, not raw speed).

Will the Two Ajax Responses Interleave in res?

Yes, absolutely—this is a flaw in the original example (likely intentional to focus on the chunking pattern, not data ordering). Here's why:

  • The two ajax calls are independent and asynchronous. There's no guarantee which one will return first.
  • Both responses use the same global res array. If the second request returns first, it'll add its first 1000 processed items to res before the first request even starts processing. Then when the first request returns, it adds its chunk, then the second request's next setTimeout callback runs, adding another chunk, and so on.
  • The end result is res will be a mix of data from both requests, in an order that depends on how fast each request's chunks process.

The data arrays for each request are safe from each other (since splice modifies the original array passed to each response call), but the shared res is the problem.

Fixing the Data Interleaving

If you need to keep the data from each request separate (or combine them in a specific order), you should isolate each request's results instead of using a global array. Here's a quick adjustment:

// Store results per request URL instead of a single global array
const requestResults = {};

function processResponse(url, data) {
  const chunk = data.splice(0, 1000);
  
  // Initialize the result array for this URL if it doesn't exist
  if (!requestResults[url]) {
    requestResults[url] = [];
  }
  
  requestResults[url] = requestResults[url].concat(
    chunk.map(val => val * 2)
  );

  if (data.length > 0) {
    setTimeout(() => processResponse(url, data), 0);
  } else {
    // Check if both requests are done processing
    if (Object.keys(requestResults).length === 2) {
      // Combine results in the order you want (e.g., first URL then second)
      const finalResults = requestResults["http://some.url.1"].concat(
        requestResults["http://some.url.2"]
      );
      // Do something with your ordered results here
      console.log("Final ordered results:", finalResults);
    }
  }
}

// Pass the URL to the response handler to track which request is which
ajax("http://some.url.1", data => processResponse("http://some.url.1", data));
ajax("http://some.url.2", data => processResponse("http://some.url.2", data));

This way, each request's processed data stays separate until you're ready to combine them in a controlled way.


内容的提问来源于stack exchange,提问作者Saher Elgendy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:56:41