delay工具5大实战场景:网页抓取、限流请求、测试等待的终极组合拳
2026/8/24 17:29:37 网站建设 项目流程

delay工具5大实战场景:网页抓取、限流请求、测试等待的终极组合拳

【免费下载链接】delayDelay a promise a specified amount of time项目地址: https://gitcode.com/gh_mirrors/de/delay

delay是一个专用于 JavaScript/TypeScript 的 Promise 延迟工具库,核心功能是「延迟一个 Promise 指定毫秒数后再执行后续代码」,一行await delay(100)就能让程序优雅地暂停。它比原生setTimeout更强大:支持无限时长(突破 24.8 天上限)、随机延迟区间、信号取消、提前清除等待,是网页抓取、限流请求、测试等待三大高频场景的终极组合拳。

💡小贴士:如果你的项目只跑在 Node.js 20+ 上,也可以用内置的import {setTimeout} from 'node:timers/promises'实现简单等待,但需要浏览器兼容或更多高级特性时,delay依然是首选。

快速上手:一条命令安装 delay 并运行

安装只需一条命令:

npm install delay

基本用法非常简单,导入后直接await即可:

import delay from 'delay'; console.log('开始'); await delay(1000); // 等待 1 秒 console.log('1 秒后执行到这里');

库的核心实现位于index.js,TypeScript 类型定义在index.d.ts,完整 API 说明见readme.md

场景一:网页抓取的人为节奏控制(反爬更友好)

批量抓取网页时,如果请求像机关枪一样密集发出,很容易被目标站点识别为爬虫并封禁 IP。delay提供的rangeDelay可以在最小和最大毫秒之间随机等待,模拟真人浏览的"不规则节奏":

import {rangeDelay} from 'delay'; for (const url of urls) { await fetchPage(url); await rangeDelay(500, 2000); // 每页之间随机等 0.5~2 秒 }

随机间隔让请求节奏更自然,比固定间隔的delay(1000)更贴近真实用户行为,抓取任务也更安全。这正是rangeDelay在官方文档中被特别推荐用于网页抓取的原因。

场景二:限流请求:批量调用接口自动控速

调用第三方 API 时,很多服务都有速率限制(例如「每分钟最多 60 次」)。用delay就能把控速逻辑写得清清楚楚:

import delay from 'delay'; const tasks = [...Array(100)]; for (const task of tasks) { await callApi(task); await delay(1000); // 每秒最多 1 次,100 个任务约 100 秒跑完 }

相比手写setTimeout回调嵌套或自己拼队列,await delay()的代码几乎是线性阅读的:先调用、再等待、再调用——逻辑一目了然,新人接手也零门槛。

场景三:测试等待:让 flaky 测试告别超时误报

写单元测试时经常遇到"等 DOM 渲染完成""等动画结束"这类需求。这里有两个delay的杀手锏:

1. 用rangeDelay替代固定阈值

官方文档明确建议:断言"方法耗时不超过 X"这类测试在 CI 上可能因机器性能波动而误报。给断言留一个阈值区间会更稳:

import {rangeDelay} from 'delay'; // 性能断言前随机等待 0~200ms,避免 CI 环境抖动导致偶发失败 await rangeDelay(0, 200);

2. 用clearDelay提前结束等待

等待时间到了不一定非等不可。clearDelay可以随时终止一个尚未到期的延迟 Promise,并立即以预设值结算,让测试不必傻等:

import delay, {clearDelay} from 'delay'; const p = delay(5000, {value: 'done'}); if (conditionMet) { clearDelay(p); // 条件已满足,立刻继续,不用等满 5 秒 } console.log(await p); //=> 'done'

项目的测试文件test.js中就包含can clear a delayed resolutionresolution can be aborted with an AbortSignal等用例,可以直接参考这些写法。

场景四:取消与清理:AbortSignal 让等待可以"叫停"

有些等待必须能被打断,比如用户点击了取消按钮。delay支持传入标准的AbortSignal,一旦信号触发,等待立即以AbortError失败退出:

import delay from 'delay'; const controller = new AbortController(); buttonCancel.onclick = () => controller.abort(); // 用户点取消 try { await delay(10000, {signal: controller.signal}); // 最多等 10 秒 } catch (error) { if (error.name === 'AbortError') console.log('用户取消了,立即返回'); }

配合value选项,等待结束后还能直接拿到一个自定义结果,省得再声明一次变量:

const result = await delay(100, {value: '🦄'}); console.log(result); //=> '🦄'

场景五:自定义计时器注入:mock 时间也不破坏延迟逻辑

自动化测试框架常常需要把全局定时器 mock 掉(例如jest.useFakeTimers()),但这会让普通setTimeout失效。delay提供了createDelay,允许你注入自定义的setTimeout/clearTimeout实现,得到一个隔离的延迟实例:

import {createDelay} from 'delay'; const customDelay = createDelay({setTimeout, clearTimeout}); const result = await customDelay(100, {value: '🦄'}); console.log(result); //=> '🦄'

官方文档称这个 API 正是为"即将全局 stub 定时器、但仍要用 delay 管理测试"的场景准备的。

delay 的 4 个核心 API 一览表

API作用一句话场景
delay(ms, options?)(默认导出)延迟指定毫秒后 resolve所有需要"暂停一下"的场景
rangeDelay(min, max)在区间内随机延迟网页抓取、性能测试留阈值
clearDelay(promise)立即结束并结算一个延迟 Promise条件已满足,不必等满
createDelay({setTimeout, clearTimeout})创建注入自定义计时器的实例测试中 mock 全局时间

两个通用的options参数在所有 API 中都能用:

  • value:等待结束时 Promise 结算的值(可为任意类型,包括0null等假值);
  • signalAbortSignal信号,触发时以AbortError提前中断。

还有一个隐藏福利:delay底层依赖unlimited-timeout,因此没有原生setTimeout约 24.8 天的最大时长限制,想await delay(86400000 * 30)等一个月也完全没问题。

常见问题:delay 会阻塞浏览器或 Node 吗?

不会。await delay()只是让当前异步函数挂起等待,事件循环照常运转,其他任务(网络请求、UI 渲染)不受影响。这也是它比while循环空转等待优雅得多的原因。

写在最后:小工具,大场景

delay整个库只有index.js一个入口文件,却精准覆盖了异步开发中"等待"这件事的所有痛点:定长等待、随机等待、提前结束、随时取消、计时器注入。无论你是在写爬虫脚本、批量调接口,还是让测试少一点 flaky,await delay(...)都值得成为你的肌肉记忆。🚀

【免费下载链接】delayDelay a promise a specified amount of time项目地址: https://gitcode.com/gh_mirrors/de/delay

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询