¥
立即购买

JavaScript回调函数生成器

7 浏览
1 试用
0 购买
Dec 8, 2025更新

本提示词专门用于生成高质量的JavaScript回调函数代码,能够根据用户指定的函数名称和功能场景,自动创建符合最佳实践的异步处理函数。它支持多种回调场景配置,包括事件处理、异步操作完成回调、数据处理完成通知等,确保生成的代码具备良好的错误处理机制、参数验证和代码注释,帮助开发者快速构建可靠的JavaScript应用程序。

函数定义

/**
 * onButtonClickSafe
 * 安全的点击事件回调函数,包含参数校验、错误处理与可选的交互增强。
 *
 * 使用场景:浏览器事件处理(click)
 * 返回值:void
 *
 * @param {Event} event - 事件对象(必填),仅接受类型为 "click" 的事件。
 * @param {string} targetId - 目标元素的 id(必填,非空),必须匹配 /^[A-Za-z][\w-]{2,30}$/。
 * @param {Object} [meta={}] - 可选配置对象,默认 {}。
 *   @property {number} [meta.cooldownMs=250] - 点击冷却时间,防止误触(0~5000ms)。
 *   @property {boolean} [meta.togglePressed=false] - 若目标为按钮或 role=button,则切换 aria-pressed。
 *   @property {string} [meta.addClass] - 点击后临时添加的类名(将自动移除)。
 *   @property {number} [meta.removeClassAfterMs=150] - 临时类名移除的延时(ms)。
 *   @property {Function} [meta.onSuccess] - 成功回调:({ target, event, meta }) => void。
 *   @property {Function} [meta.onError] - 错误回调:(error, context) => void。
 */
function onButtonClickSafe(event, targetId, meta = {}) {
  'use strict';

  // 正则:以字母开头,后续 2~30 个字母/数字/下划线/连字符
  const ID_PATTERN = /^[A-Za-z][\w-]{2,30}$/;

  // 安全调用回调(不影响主流程)
  function safeCall(fn, ...args) {
    try {
      if (typeof fn === 'function') fn(...args);
    } catch (cbErr) {
      // 避免 onError/onSuccess 本身抛错影响主流程
      console.error('onButtonClickSafe: callback invocation error:', cbErr);
    }
  }

  // 参数基本校验
  const errors = [];

  if (!(event instanceof Event)) {
    errors.push('Parameter "event" must be an instance of Event.');
  } else if (event.type !== 'click') {
    errors.push(`Invalid event.type "${event.type}". Expected "click".`);
  }

  if (typeof targetId !== 'string' || targetId.trim() === '') {
    errors.push('Parameter "targetId" must be a non-empty string.');
  } else if (!ID_PATTERN.test(targetId)) {
    errors.push(`Parameter "targetId" must match pattern ${ID_PATTERN.source}.`);
  }

  if (meta == null || typeof meta !== 'object' || Array.isArray(meta)) {
    console.warn('onButtonClickSafe: "meta" should be a plain object. Falling back to {}.');
    meta = {};
  }

  if (errors.length > 0) {
    const err = new Error(`onButtonClickSafe validation failed: ${errors.join(' ')}`);
    console.error(err);
    safeCall(meta.onError, err, { event, targetId, meta });
    return; // 返回 void
  }

  // 主体逻辑(包含标准错误处理)
  try {
    const el = document.getElementById(targetId);
    if (!el) {
      const err = new Error(`Target element with id "${targetId}" not found.`);
      console.error(err);
      safeCall(meta.onError, err, { event, targetId, meta });
      return;
    }

    // 确认事件来源于目标元素或其子孙元素(避免错误匹配)
    const evtTarget = event.target;
    if (evtTarget && el !== evtTarget && !el.contains(evtTarget)) {
      console.warn(`Event target is not element #${targetId} or its descendant. Ignoring.`);
      return;
    }

    // 禁用态检查
    const isDisabled = el.hasAttribute('disabled') || el.getAttribute('aria-disabled') === 'true';
    if (isDisabled) {
      console.warn(`Element #${targetId} is disabled. Action canceled.`);
      return;
    }

    // 点击冷却(防抖/去抖:避免多次快速点击)
    const defaultCooldown = 250;
    let cooldownMs = defaultCooldown;
    if (
      typeof meta.cooldownMs === 'number' &&
      isFinite(meta.cooldownMs) &&
      meta.cooldownMs >= 0 &&
      meta.cooldownMs <= 5000
    ) {
      cooldownMs = meta.cooldownMs;
    }

    const now = Date.now();
    const cooldownUntil = Number(el.dataset.clickCooldownUntil || 0);
    if (cooldownUntil && now < cooldownUntil) {
      console.warn(`Click ignored due to cooldown for #${targetId}.`);
      return;
    }
    el.dataset.clickCooldownUntil = String(now + cooldownMs);

    // 可访问性与状态增强
    // 尝试聚焦(不滚动)
    if (typeof el.focus === 'function') {
      el.focus({ preventScroll: true });
    }

    // 若为按钮或 role=button,按需切换 aria-pressed
    const tag = el.tagName.toLowerCase();
    const isButtonLike = tag === 'button' || el.getAttribute('role') === 'button';
    if (isButtonLike && meta.togglePressed === true) {
      const pressed = el.getAttribute('aria-pressed') === 'true';
      el.setAttribute('aria-pressed', pressed ? 'false' : 'true');
    }

    // 临时添加类名(用于视觉反馈),并自动移除
    if (typeof meta.addClass === 'string' && meta.addClass.trim().length > 0) {
      const cls = meta.addClass.trim();
      el.classList.add(cls);
      const removeMs =
        typeof meta.removeClassAfterMs === 'number' && meta.removeClassAfterMs >= 0
          ? meta.removeClassAfterMs
          : 150;
      if (removeMs > 0) {
        setTimeout(() => {
          try {
            el.classList.remove(cls);
          } catch (e) {
            console.warn('onButtonClickSafe: failed to remove class:', e);
          }
        }, removeMs);
      }
    }

    // 记录最后点击时间(可供外部参考)
    el.dataset.lastClickedAt = String(now);

    // 派发一个完成事件(可在外部监听)
    el.dispatchEvent(
      new CustomEvent('onButtonClickSafe:done', {
        bubbles: true,
        detail: { targetId, meta }
      })
    );

    // 成功回调
    safeCall(meta.onSuccess, { target: el, event, meta });
  } catch (err) {
    console.error('onButtonClickSafe runtime error:', err);
    safeCall(meta.onError, err, { event, targetId, meta });
  }
}

参数说明

  • event: Event,必填。必须为浏览器点击事件(event.type === 'click'),否则函数直接返回并记录错误。
  • targetId: string,必填,非空。必须匹配正则 ^[a-zA-Z][\w-]{2,30}$,即以字母开头,长度 3~31(含)且仅包含字母/数字/下划线/连字符。
  • meta: object,选填,默认 {}。
    • meta.cooldownMs: number,点击冷却时间,范围 0~5000ms,默认 250ms。
    • meta.togglePressed: boolean,若目标元素是
    • meta.addClass: string,点击后临时添加的类名,用于视觉反馈。
    • meta.removeClassAfterMs: number,移除临时类名的延时(ms),默认 150ms。
    • meta.onSuccess: Function,成功后回调,签名:({ target, event, meta }) => void。
    • meta.onError: Function,错误回调,签名:(error, context) => void。

使用示例

<button id="submitBtn" type="button" aria-pressed="false">提交</button>
<script>
  // 绑定点击事件
  document.getElementById('submitBtn').addEventListener('click', (e) => {
    onButtonClickSafe(e, 'submitBtn', {
      cooldownMs: 300,
      togglePressed: true,
      addClass: 'clicked',
      removeClassAfterMs: 200,
      onSuccess: ({ target, event, meta }) => {
        // 自定义成功逻辑(例如发起异步请求)
        console.log('Clicked:', target.id, 'event:', event.type, 'meta:', meta);
      },
      onError: (error, context) => {
        // 标准错误处理:记录日志或提示用户
        console.error('Click handler error:', error, context);
      }
    });
  });

  // 可选:监听完成事件
  document.addEventListener('onButtonClickSafe:done', (evt) => {
    const { targetId, meta } = evt.detail || {};
    console.log('onButtonClickSafe done for:', targetId, meta);
  });
</script>

注意事项

  • 函数仅处理 click 事件;其他事件类型将被忽略并记录警告/错误。
  • 目标元素必须存在且 id 合法,否则函数会安全返回并调用 onError(若提供)。
  • 函数包含基础的“冷却”机制,避免快速多次点击导致重复处理,可通过 meta.cooldownMs 调整或设为 0 关闭。
  • 对按钮或 role="button" 元素,启用 meta.togglePressed 可提升可访问性(ARIA 状态同步)。
  • 函数不会调用 event.preventDefault 或 event.stopPropagation,保持中性行为;如需阻止默认行为或冒泡,请在外部自行控制。
  • 该函数适用于浏览器环境(需要 DOM 和 CustomEvent);在非浏览器环境中不适用。
  • 代码避免使用不安全操作(如直接 innerHTML 注入),并通过 try/catch 与回调保护降低异常对流程的影响。

函数定义

/**
 * onUploadFinished
 * 异步上传完成后的回调函数(Promise 风格),对参数进行严格校验并提供增强的错误处理。
 *
 * 约定:
 * - 若 err 存在则立刻短路(不再处理 result),并返回一个被拒绝的 Promise。
 * - 若 result 存在则校验 result.url 必须以 "https://" 开头,result.size 必须为正数。
 * - durationMs(上传耗时,毫秒)可选,若提供必须为非负有限数。
 *
 * @param {Error|null} err - 必填。错误对象;若不为 null/undefined 即表示上传失败。
 * @param {{url: string, size: number}|undefined|null} result - 选填。上传结果对象,包含资源 URL 与大小。
 * @param {number|undefined|null} durationMs - 选填。上传耗时(毫秒)。
 * @returns {Promise<void>} - Promise<void>,成功时 resolve;校验失败或上传失败时 reject。
 */
async function onUploadFinished(err, result, durationMs) {
  // --- 基本参数存在性与类型校验 ---
  if (typeof err === 'undefined') {
    throw new TypeError('缺少必填参数 "err"(Error|null)。');
  }

  // 若存在错误则短路:不再处理 result,直接拒绝 Promise
  if (err !== null && err !== undefined) {
    const isValidDuration =
      typeof durationMs === 'number' && Number.isFinite(durationMs) && durationMs >= 0;

    const normalized = err instanceof Error
      ? err
      : new Error(`上传失败${isValidDuration ? `(耗时 ${durationMs} ms)` : ''}:${String(err)}`);

    // 为调试增强上下文信息(不影响错误堆栈)
    if (isValidDuration) {
      // 附加只读上下文,避免污染原型链或引入安全风险
      Object.defineProperty(normalized, 'context', {
        value: { durationMs },
        enumerable: false,
        configurable: false,
        writable: false
      });
    }

    throw normalized; // async 函数中 throw => 返回被拒绝的 Promise
  }

  // 校验 durationMs(若提供)
  if (durationMs !== undefined && durationMs !== null) {
    if (typeof durationMs !== 'number' || !Number.isFinite(durationMs) || durationMs < 0) {
      throw new TypeError('参数 "durationMs" 必须为非负的有限数。');
    }
  }

  // 若 result 未提供,按约定可正常结束(无更多信息可处理)
  if (result === undefined || result === null) {
    return;
  }

  // --- 对 result 的结构与字段进行严格校验 ---
  if (typeof result !== 'object' || Array.isArray(result)) {
    throw new TypeError('参数 "result" 必须为对象 { url: string, size: number }。');
  }

  const { url, size } = result;

  if (typeof url !== 'string') {
    throw new TypeError('result.url 必须为字符串。');
  }

  const trimmedUrl = url.trim();
  if (!trimmedUrl.startsWith('https://')) {
    throw new Error('result.url 必须以 "https://" 开头。');
  }

  // 进一步保证 URL 合法性(防止不可解析的 URL)
  try {
    // 若不可解析将抛错
    new URL(trimmedUrl);
  } catch {
    throw new Error('result.url 不是一个可解析的合法 URL。');
  }

  if (typeof size !== 'number' || !Number.isFinite(size) || size <= 0) {
    throw new TypeError('result.size 必须为一个大于 0 的有限数。');
  }

  // 至此所有校验通过;此处可以安全地进行后续异步处理(如统计/通知等)
  // 该示例不做外部副作用以避免环境不兼容,仅完成回调职责。
  return;
}

参数说明

  • err
    • 类型:Error|null(必填)
    • 作用:表示上传是否失败。若不为 null/undefined,则视为失败并短路,立即返回被拒绝的 Promise。
  • result
    • 类型:object(选填),结构为 { url: string, size: number }
    • 作用:上传成功的结果。
    • 校验:url 必须以 "https://" 开头且可被 URL 解析;size 必须为大于 0 的有限数。
  • durationMs
    • 类型:number(选填)
    • 作用:上传耗时(毫秒)。
    • 校验:若提供,必须为非负的有限数。

使用示例

// 示例 1:在 async/await 流程中使用
async function handleUpload() {
  try {
    // 假设外部上传得到如下结果
    const err = null;
    const result = { url: 'https://cdn.example.com/file.png', size: 24567 };
    const durationMs = 1320;

    await onUploadFinished(err, result, durationMs);
    console.log('上传完成并通过校验,后续处理...');
  } catch (e) {
    console.error('上传失败或结果不合法:', e);
    // 根据业务进行错误上报/提示等
  }
}

// 示例 2:上传失败的场景
onUploadFinished(new Error('网络异常'), null, 980)
  .then(() => {
    // 正常不会进到这里,因为会被拒绝
  })
  .catch((e) => {
    console.error('捕获到失败:', e);
  });

// 示例 3:与传统回调风格库配合(确保消费返回的 Promise,避免未处理的拒绝)
function someUploadLibrary(file, cb) {
  // 模拟:1 秒后触发回调
  setTimeout(() => {
    cb(null, { url: 'https://cdn.example.com/a.mp4', size: 1024 * 1024 }, 1000);
  }, 1000);
}

someUploadLibrary({/* ... */}, (err, result, durationMs) => {
  // 一定要消费 Promise(then/catch 或 await),避免未处理的 Promise 拒绝
  onUploadFinished(err, result, durationMs)
    .then(() => {
      console.log('库回调处理成功');
    })
    .catch((e) => {
      console.error('库回调处理失败:', e);
    });
});

注意事项

  • 函数返回 Promise,请务必使用 await 或 .then/.catch 消费返回的 Promise,避免产生未处理的 Promise 拒绝。
  • 当 err 存在时会短路并拒绝 Promise;result 在该情况下会被忽略。
  • URL 校验要求以 https 开头并可被 URL 构造器解析;请确保上传服务返回的是合法的 HTTPS 地址。
  • size 必须为正数且有限;durationMs(若提供)必须为非负有限数。
  • 函数不引入外部副作用(如网络请求或环境特定操作),以保证在浏览器与 Node.js 环境均可安全使用。

函数定义

/**
 * onCsvParsed
 * 回调函数:在CSV解析完成后执行,进行基础参数校验与警告处理。
 *
 * 约束校验:
 * - summary.rows 必须等于 records.length
 * - summary.columns 必须为 > 0 的正整数
 *
 * 返回:
 * - { ok: boolean }:校验成功为 true,失败为 false
 *
 * @param {string[]} records - 必填。CSV的每一行字符串组成的数组。
 * @param {{rows:number, columns:number}} summary - 必填。解析结果摘要信息。
 * @param {string[]} [warnings] - 选填。解析过程中产生的警告信息列表。
 * @returns {{ok:boolean}}
 */
function onCsvParsed(records, summary, warnings) {
  'use strict';

  try {
    // 参数基本类型校验
    if (!Array.isArray(records)) {
      console.error('[onCsvParsed] 参数错误:records 必须为数组。');
      return { ok: false };
    }

    // records 元素类型校验(string[])
    const invalidRecordIndex = records.findIndex(r => typeof r !== 'string');
    if (invalidRecordIndex !== -1) {
      console.error(`[onCsvParsed] 参数错误:records[${invalidRecordIndex}] 不是字符串。`);
      return { ok: false };
    }

    // summary 结构与数值校验
    if (summary == null || typeof summary !== 'object') {
      console.error('[onCsvParsed] 参数错误:summary 必须为对象。');
      return { ok: false };
    }

    const { rows, columns } = summary;

    if (!Number.isInteger(rows) || rows < 0) {
      console.error('[onCsvParsed] 参数错误:summary.rows 必须为非负整数。');
      return { ok: false };
    }

    if (!Number.isInteger(columns) || columns <= 0) {
      console.error('[onCsvParsed] 参数错误:summary.columns 必须为大于 0 的正整数。');
      return { ok: false };
    }

    // 业务校验:rows 等于 records.length
    if (rows !== records.length) {
      console.error(
        `[onCsvParsed] 校验失败:summary.rows(${rows}) 与 records.length(${records.length}) 不一致。`
      );
      return { ok: false };
    }

    // warnings 选填校验与处理
    if (warnings !== undefined) {
      if (!Array.isArray(warnings)) {
        console.error('[onCsvParsed] 参数错误:warnings(若提供)必须为字符串数组。');
        return { ok: false };
      }
      const invalidWarningIndex = warnings.findIndex(w => typeof w !== 'string');
      if (invalidWarningIndex !== -1) {
        console.error(`[onCsvParsed] 参数错误:warnings[${invalidWarningIndex}] 不是字符串。`);
        return { ok: false };
      }

      if (warnings.length > 0) {
        // 基础级别处理:输出警告日志
        console.warn('[onCsvParsed] 警告:', warnings.join(' | '));
      }
    }

    // 所有校验通过
    return { ok: true };
  } catch (err) {
    // 基础错误处理:捕获异常并输出日志
    console.error('[onCsvParsed] 执行异常:', err);
    return { ok: false };
  }
}

参数说明

  • records (array, 必填, string[]): CSV解析得到的每一行字符串的数组。必须是纯字符串数组。
  • summary (object, 必填, { rows:number, columns:number }): 解析摘要信息。
    • rows: 解析到的行数,必须为非负整数,且必须等于 records.length。
    • columns: 每行的列数,必须为大于 0 的正整数。
  • warnings (string[], 选填): 解析过程中产生的文本警告信息列表。若提供,必须为字符串数组。

使用示例

// 假设 parseCsv 是某个解析函数,解析完成后调用回调 onCsvParsed
function parseCsv(csvText, callback) {
  // 伪代码:按行拆分
  const lines = csvText.split('\n').map(s => s.trim()).filter(Boolean);

  // 简单计算列数(以第一行的逗号数量 + 1 为列数)
  const columns = lines.length > 0 ? (lines[0].split(',').length) : 0;

  // 模拟警告:如果存在空行或列数不一致
  const warnings = [];
  const inconsistentRowIndex = lines.findIndex(
    line => line.split(',').length !== columns
  );
  if (inconsistentRowIndex !== -1) {
    warnings.push(`第 ${inconsistentRowIndex + 1} 行列数不一致`);
  }

  const summary = { rows: lines.length, columns };

  // 调用回调进行校验
  const result = callback(lines, summary, warnings);
  return result;
}

// 使用演示
const csv = 'a,b,c\n1,2,3\nx,y,z';
const result = parseCsv(csv, onCsvParsed);

if (result.ok) {
  console.log('CSV 解析与校验成功。');
} else {
  console.log('CSV 解析或校验失败,请检查输入与摘要信息。');
}

注意事项

  • 本回调为同步执行,返回简单的 {ok:boolean}。若需要异步处理(如网络上报),请在外层封装为 Promise 或使用异步API。
  • 参数校验为基础级别,默认通过 console 输出错误与警告,不会抛出异常以避免中断调用方流程。
  • 请确保传入的 summary 与 records 来源一致,尤其是 rows 与 records.length 的一致性。
  • columns 的计算应在解析阶段完成并保证为正整数;当列数为 0 时视为非法输入。
  • 函数不修改传入的 records 与 warnings,若需要清洗数据,请在解析阶段或另行处理。

示例详情

解决的问题

为前端与 Node.js 开发者、技术负责人、外包交付团队提供一套“即写即用”的回调函数生成解决方案:用一句描述即可一键生成高质量的 JavaScript 回调函数,自动补齐错误处理、参数校验、边界检查与清晰注释,并给出可直接运行的调用示例;根据不同业务场景(事件处理、异步完成通知、数据处理结束)自动匹配合适的代码结构与写法,确保风格统一、可读可维护;帮助团队缩短评审与联调时间、降低缺陷率与返工成本,加速交付与上线;通过可复用的提示词让个人高效产出、让团队沉淀标准,从而提升试用意愿并转化为持续付费价值。

适用用户

前端工程师

快速产出点击、滚动、表单等事件回调与数据加载完成回调,统一参数校验与错误提示,缩短开发与联调时间。

Node.js开发者

便捷生成文件读写、网络请求、任务队列等异步回调,按容错级别自动处理异常并记录提示,减少线上排障成本。

个人与初创团队

通过模板化配置,几分钟内搭好核心回调骨架,从原型验证到上线复用同一风格,显著降低返工与维护压力。

特征总结

一键生成高质量回调函数,按事件、异步、数据处理等场景自动定制逻辑,并与命名需求匹配。
自动补齐参数校验与边界检查,减少线上故障,显著降低排查与回滚成本。
内置稳健错误处理策略,可按容错级别切换,避免异步链路悄然失败,并保留清晰提示。
自动生成注释与使用示例,新手也能快速上手,团队沟通与评审成本更低。
支持浏览器与服务端多环境调用,兼顾兼容性与性能,减少重复封装工作量。
基于模板化与参数化配置,按需生成函数签名与流程,保持风格统一与团队规范一致。
内置代码质量校验与规范化输出,自动消除常见异味与陷阱,提交前更安心。
快速搭建可靠异步流程,减少手写回调出错概率,加速原型到上线全流程。
预设多类回调场景,如事件、完成通知、数据变更,省去反复查资料,提升交付速度。
提供清晰输入表单指引,仅需填写名称与场景,即可生成可用代码片段,并可直接粘贴使用。

如何使用购买的提示词模板

1. 直接在外部 Chat 应用中使用

将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。

2. 发布为 API 接口调用

把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。

3. 在 MCP Client 中配置使用

在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。

AI 提示词价格
¥20.00元
先用后买,用好了再付款,超安全!

您购买后可以获得什么

获得完整提示词模板
- 共 612 tokens
- 4 个可调节参数
{ 函数名称 } { 回调场景 } { 错误处理级别 } { 参数配置 }
获得社区贡献内容的使用权
- 精选社区优质案例,助您快速上手提示词
使用提示词兑换券,低至 ¥ 9.9
了解兑换券 →
限时半价

不要错过!

半价获取高级提示词-优惠即将到期

17
:
23
小时
:
59
分钟
:
59