usmanyunusov / nanospinner

🌀 The simplest and tiniest terminal spinner for Node.js
https://npm.im/nanospinner
ISC License
183 stars 15 forks source link

Node throws memory leak warning causing script to fail #13

Closed Mitsunee closed 2 years ago

Mitsunee commented 2 years ago

I am currently working on a node script to update a dataset generated from a bunch fetch requests. I decided to add nanospinners to the fetchData function I have set up to fetch one or multiple json endpoints and it appears to have caused a memory leak:

(node:17186) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 SIGINT listeners added to [process]. Use emitter.setMaxListeners() to increase limit
    at _addListener (events.js:390:17)
    at process.addListener (events.js:406:10)
    at Object.start (/home/mitsunee/Projects/fgo-tools/node_modules/nanospinner/index.js:54:15)
    at fetchData (file:///home/mitsunee/Projects/fgo-tools/scripts/update-upgrades-data.mjs:230:11)
    at fetchQuestData (file:///home/mitsunee/Projects/fgo-tools/scripts/update-upgrades-data.mjs:245:42)
    at main (file:///home/mitsunee/Projects/fgo-tools/scripts/update-upgrades-data.mjs:401:44)

Here is an excerpt from the script in question (I haven't pushed my changes yet, so I'm copypasting it here for reference)

async function fetchData(url, defaultValue, message = "Fetching Data") {
  const spinner = createSpinner(message);
  const _fetch = async (url, defaultValue) => {
    try {
      const res = await fetch(url);
      if (!res.ok) {
        if (defaultValue === undefined) {
          spinner.error(`error while fetching '${url}'`);
          process.exit(2);
        }
        return defaultValue;
      }
      return await res.json();
    } catch (e) {
      if (defaultValue === undefined) {
        spinner.error(`received invalid data from '${url}'`);
        process.exit(2);
      }
      return defaultValue;
    }
  };

  let res;
  spinner.start();
  if (url instanceof Array) {
    res = await Promise.all(
      url.map(async item => await _fetch(item, defaultValue))
    );
  } else {
    res = await _fetch(url, defaultValue);
  }
  spinner.success();
  return res;
}

The fetch() api is provided by node-fetch. The warning occurs after this function has ran 10 times, causing it to return invalid data (possibly undefined?). fetchQuestData is merely a wrapper around fetchData() that caches results in a Map. It appears the warning is thrown here:

https://github.com/usmanyunusov/nanospinner/blob/master/index.js#L47-L57

usmanyunusov commented 2 years ago

Fix Release 0.3.0