{"id":15303,"library":"callforth","title":"Callforth Promise Utilities","description":"Callforth is a lightweight utility library designed to streamline common asynchronous JavaScript patterns by converting them into Promise-based operations. Currently at version 0.4.0, it offers a small collection of functions to replace traditional callback APIs, enabling developers to leverage `async/await` syntax for cleaner, more readable code. Its primary utilities include `eventOn` for awaiting specific events on any `EventTarget`, `timeout` for promise-based delays, and `polling` for repeatedly checking a predicate until it returns true or a maximum number of tries is reached. The library differentiates itself by focusing on simplifying frequently re-implemented patterns into a tiny, focused package, aiming to provide a 'don't callback, callforth' experience. There isn't a specified strict release cadence, but as a pre-1.0.0 project, updates are likely as needed.","status":"active","version":"0.4.0","language":"javascript","source_language":"en","source_url":"https://github.com/gruhn/callforth","tags":["javascript"],"install":[{"cmd":"npm install callforth","lang":"bash","label":"npm"},{"cmd":"yarn add callforth","lang":"bash","label":"yarn"},{"cmd":"pnpm add callforth","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Primary ESM import for awaiting DOM or Web Worker events. CommonJS `require` works but ESM is preferred in modern Node.js and browser environments.","wrong":"const eventOn = require('callforth').eventOn","symbol":"eventOn","correct":"import { eventOn } from 'callforth'"},{"note":"A named import. Attempting a default import for `timeout` (or other utilities) will result in `undefined`.","wrong":"import timeout from 'callforth'","symbol":"timeout","correct":"import { timeout } from 'callforth'"},{"note":"For browser-global UMD usage, `window.callforth` contains all utilities. Directly destructuring from `window.callforth` is correct for UMD, but `import` syntax is for module environments.","wrong":"const { polling } = window.callforth","symbol":"polling","correct":"import { polling } from 'callforth'"}],"quickstart":{"code":"import { eventOn, timeout } from \"callforth\";\n\nasync function loadAndTrackScript(url: string) {\n  console.log(`Attempting to load script from: ${url}`);\n  const script = document.createElement(\"script\");\n  script.src = url;\n  script.async = true;\n\n  // Append to document to start loading\n  document.head.appendChild(script);\n\n  try {\n    // Await either 'load' for success or 'error' for failure\n    const result = await eventOn(script, \"load\", \"error\");\n\n    if (result.type === \"load\") {\n      console.log(`Script loaded successfully from ${url} at ${new Date().toLocaleTimeString()}.`);\n      await timeout(500); // Simulate a small delay after loading\n      console.log(\"Further processing after a short pause.\");\n    } else if (result.type === \"error\") {\n      console.error(`Failed to load script from ${url}.`);\n    }\n  } catch (err) {\n    console.error(`An unexpected error occurred during script loading for ${url}:`, err);\n  } finally {\n    // Clean up the script element after it's done\n    if (script.parentNode) {\n      script.parentNode.removeChild(script);\n    }\n    console.log(`Cleanup for ${url} complete.`);\n  }\n}\n\n// Example usage: Try loading a valid and an invalid script\nloadAndTrackScript('https://unpkg.com/react@18/umd/react.production.min.js');\n// In a real scenario, you'd replace 'nonexistent.js' with a URL that genuinely fails\n// loadAndTrackScript('https://example.com/nonexistent.js');","lang":"typescript","description":"Demonstrates `eventOn` to asynchronously load a script and wait for its 'load' or 'error' event, combined with `timeout` for controlled delays, showcasing common browser-side async patterns."},"warnings":[{"fix":"Always review the changelog when updating minor versions. Consider pinning to exact versions or exercising caution with automatic updates in production environments.","message":"As a pre-1.0.0 package (current version 0.4.0), `callforth` does not strictly adhere to SemVer. Minor version updates (e.g., 0.x.0 to 0.y.0) may introduce breaking changes without prior deprecation warnings.","severity":"breaking","affected_versions":">=0.1.0"},{"fix":"If continuous listening is required, you must re-call `eventOn` or use standard `addEventListener` for persistent behavior. `eventOn` is best suited for 'one-shot' event waiting.","message":"The `eventOn` utility automatically removes the event listener after the first successful event or error event, ensuring the promise resolves or rejects once. This is by design but can be a 'gotcha' if you expect the listener to persist for multiple events.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Change `const { symbol } = require('callforth')` to `import { symbol } from 'callforth'`.","cause":"Attempting to use CommonJS `require()` syntax in a JavaScript file that is treated as an ES module (e.g., due to `\"type\": \"module\"` in `package.json` or a `.mjs` extension).","error":"ReferenceError: require is not defined in ES module scope"},{"fix":"Ensure the `target` parameter for `eventOn` is an object that correctly implements the `EventTarget` interface, such as `document.body`, `window`, or a `new EventTarget()` instance.","cause":"The first argument passed to `eventOn` is not a valid `EventTarget` (e.g., a DOM element, `window`, `document`, or a custom object implementing `addEventListener` and `removeEventListener`).","error":"TypeError: eventTarget.addEventListener is not a function"}],"ecosystem":"npm"}