AsyncLocalStorage解决了什么问题

121 阅读1分钟
http.get('http://localhost:4000/', (res) => {
  let chunkCount = 0;
  res.on('data', (chunk) => {
    console.log('Received a chunk of data:');
    chunkCount++;
    fs.writeFile(`stream-chunk${chunkCount}.html`, chunk, (err) => {
        if (err) throw err;
        console.log(`The chunk ${chunkCount} was saved!`);
    });
  });
});

这段代码有个隐藏的问题,在保存文件的回调函数中,当我们真正输出 chunkCount 的时候,每个回调函数输出的值都是一样的。怎么样让每个回调函数拿到自己的 chunkCount 呢?

一个简单的方式是使用临时变量

res.on('data', (chunk) => {
  console.log('Received a chunk of data:');
  chunkCount++;
  let currentChunkCount = chunkCount;
  fs.writeFile(`stream-chunk${currentChunkCount}.html`, chunk, (err) => {
    if (err) throw err;
    console.log(`The chunk ${currentChunkCount} was saved!`);
  });
});

但是这样很不优雅,有hack。所以nodejs出了 AsyncLocalStorage 来解决这个问题

import http from 'http';
import fs from 'fs';
import { AsyncLocalStorage } from "node:async_hooks";

const asyncLocalStorage = new AsyncLocalStorage();

http.get('http://localhost:4000/', (res) => {
  let chunkCount = 0;
  res.on('data', (chunk) => {
    console.log('Received a chunk of data:');
    chunkCount++;

    asyncLocalStorage.run(chunkCount, () => {
      fs.writeFile(`stream-chunk${asyncLocalStorage.getStore()}.html`, chunk, (err) => {
        if (err) throw err;
        console.log(`The chunk ${asyncLocalStorage.getStore()} was saved!`);
      });
    });
  });

  res.on('end', () => {
    console.log('No more data.');
  });
});