如何重试 Promise 决议 N 次,并在尝试之间有延迟?

2024-01-14

我想要一些 JavaScript 代码将 3 个东西作为参数:

  • 返回 Promise 的函数。
  • 最大尝试次数。
  • 每次尝试之间的延迟。

我最终做的是使用for环形。我不想使用递归函数:这样,即使有 50 次尝试,调用堆栈也不会长 50 行。

这里是打字稿代码版本:

/**
 * @async
 * @function tryNTimes<T> Tries to resolve a {@link Promise<T>} N times, with a delay between each attempt.
 * @param {Object} options Options for the attempts.
 * @param {() => Promise<T>} options.toTry The {@link Promise<T>} to try to resolve.
 * @param {number} [options.times=5] The maximum number of attempts (must be greater than 0).
 * @param {number} [options.interval=1] The interval of time between each attempt in seconds.
 * @returns {Promise<T>} The resolution of the {@link Promise<T>}.
 */
export async function tryNTimes<T>(
    {
        toTry,
        times = 5,
        interval = 1,
    }:
        {
            toTry: () => Promise<T>,
            times?: number,
            interval?: number,
        }
): Promise<T> {
    if (times < 1) throw new Error(`Bad argument: 'times' must be greater than 0, but ${times} was received.`);
    let attemptCount: number;
    for (attemptCount = 1; attemptCount <= times; attemptCount++) {
        let error: boolean = false;
        const result = await toTry().catch((reason) => {
            error = true;
            return reason;
        });

        if (error) {
            if (attemptCount < times) await delay(interval);
            else return Promise.reject(result);
        }
        else return result;
    }
}

The delay上面使用的函数是一个约定的超时:

/**
 * @function delay Delays the execution of an action.
 * @param {number} time The time to wait in seconds.
 * @returns {Promise<void>}
 */
export function delay(time: number): Promise<void> {
    return new Promise<void>((resolve) => setTimeout(resolve, time * 1000));
}

澄清一下:上面的代码works,我只是想知道这是否是一种“好的”方法,如果不是,我该如何改进它。

有什么建议吗?在此先感谢您的帮助。


我不想使用递归函数:这样,即使有 50 次尝试,调用堆栈也不会长 50 行。

这不是一个好的借口。调用堆栈不会因异步调用而溢出,并且当递归解决方案比迭代解决方案更直观时,您可能应该采用它。

我最终做的是使用for环形。这是一种“好”的做法吗?如果不是,我该如何改进?

The for循环很好。有点奇怪,它开始于1不过,基于 0 的循环更为惯用。

然而,不好的是你奇怪的错误处理。那个布尔值errorflag 不应在您的代码中占有一席之地。Using .catch() is fine https://stackoverflow.com/questions/44663864/correct-try-catch-syntax-using-async-await, but try/catch也会同样有效,并且应该是首选。

export async function tryNTimes<T>({ toTry, times = 5, interval = 1}) {
    if (times < 1) throw new Error(`Bad argument: 'times' must be greater than 0, but ${times} was received.`);
    let attemptCount = 0
    while (true) {
        try {
            const result = await toTry();
            return result;
        } catch(error) {
            if (++attemptCount >= times) throw error;
        }
        await delay(interval)
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何重试 Promise 决议 N 次,并在尝试之间有延迟? 的相关文章

随机推荐

  • Go的interface{}和C中的void*一样吗?

    由于类型变量interface 可以有任何值 这是否意味着它本质上是一个像 C 中的 void 一样的通用指针 而C的void 指针和 Go 的interface 变量共享可以存储任意类型的属性 但有一个很大的区别 Go 接口变量还存储它们
  • 可以用jade/pug 编写PHP 吗?

    是否可以 如果是这样 怎么办 如果不是 如果我需要在文档中编写 PHP 我是否必须放弃 pug 环顾四周后 我没有找到任何人解决了这个问题 您可以将 PHP 嵌入到 Pug 模板中 就像您希望通过相对不受干扰的任何文字纯文本一样 有文档中涵
  • Xcode 11 升级 |找不到 iPhone X 模拟器 | XRPackageModel 9.0.omo

    自从升级后还有其他人得到这个Xcode 10 3 https developer apple com documentation xcode release notes xcode 10 3 release notes to Xcode 1
  • WPF 拖动滚动功能无法正常工作

    我想在我的应用程序中实现拖动滚动功能 但在路上遇到了问题 有谁能够帮助我 我有一个 ScrollViewer 里面有一个 ItemsControl 在 ItemsTemplate 中我有一个 UserControl 我想将该 UserCon
  • UserWarning:X 没有有效的特征名称,但 LogisticRegression 已安装了特征名称

    我在 Flask 中编写了一个程序来获取用户的输入 以输入长度和宽度来预测鱼的类型 但是当我输入时 它会显示一个错误 称为 UserWarning X does not have valid feature names but Logist
  • 如何使用 6*k +- 1 规则生成素数

    我们知道 3 以上的所有素数都可以使用以下方法生成 6 k 1 6 k 1 然而 从上述公式生成的所有数字都不是素数 For Example 6 6 1 35 which is clearly divisible by 5 为了消除这种情况
  • 获取 SQL 中另一列的每个值的最常见值

    我有一个这样的表 Column Type Modifiers country text food id int eaten date 对于每个国家 我想要获得最常吃的食物 我能想到的最好的 我正在使用 postgres 是 CREATE T
  • 在 ElasticSearch 中保存用户搜索查询的最佳方式?

    我正在开发使用 ElasticSearch 和 SQL 数据库的应用程序 那么 保存用户搜索查询并显示统计信息 例如最流行的请求是什么 的最佳方法是什么 最简单的方法就是保存在SQL数据库中并统计 但也许 ElasticSearch 中内置
  • 计算pyspark数据框中的地理距离

    我的数据框 DF spark createDataFrame 114 038696 22 5315 114 047302 22 531799 114 027901 22 5228 114 026299 22 5238 114 026299
  • 当密码和确认密码输入错误时,错误响应 500 不会显示

    当密码和确认密码输入正确时 我的响应成功显示 但是当它不匹配时 它不会显示其他部分 不显示任何内容 请指导我 需要帮助 提前致谢 这是当邮递员中密码和确认密码输入错误时我的回复 status 500 message Could not re
  • PhoneGap 3.1 构建设备未定义

    我有一个煎茶触摸项目 我是用phonegap 2 9构建的 并且工作正常device uuid返回设备ID 当我尝试使用 3 1 device uuid 进行构建时 抛出 设备未定义 错误 我的配置 xml
  • 使用 XPATH 选择所有其他节点

    给定任意数量的节点来选择
  • 当两个标记相邻时,Google 地图错误的标记单击事件

    我已经为标记应用了自定义 PNG 图像 与默认标记聚类器圆的大小大致相同 并且发生了这种奇怪的事情 当两个标记靠近时 但即使它们不重叠 我需要点击一个标记两次 因为第一次点击错误地给了我前一个标记 That is 有两个标记 A 和 B 彼
  • React Native WebView 未加载源

    我正在遵循 React Native 文档中的示例 但不知道为什么我的 WebView 无法加载网站 这是我的代码 Sample React Native App https github com facebook react native
  • 你可以让 mongo $push 前置而不是附加吗?

    我希望在我的集合的开头添加push add 而不是在执行mongo push 时附加到末尾 是否可以进行原子推送更新 将元素添加为第一个而不是最后一个 2014年更新 是的你可以 http docs mongodb org manual r
  • WPF FlowDocument 绑定

    我正在使用微软的XAML HTML 转换器 http msdn microsoft com en us library aa972129 aspx将 HTML 从数据库转换为 XAML 字符串 Microsoft 转换器似乎正确设置了文本格
  • urlencode() 是否足以阻止 2011 年的所有 SQL 注入攻击

    我正在将一些简单的用户数据传递到 mysql 数据库中 PHP 的 urlencode 返回一个字符串 其中包含除 之外的所有非字母数字字符 已替换为百分号 后跟两个十六进制数字 我不担心空格变成加号 或其他格式问题 我也不担心 XSS 和
  • DPDK“端口数必须为偶数”一台以太网设备

    我正在尝试从 DPDK 源代码运行骨架示例 但每当我尝试在 make 过程后构建代码时 我都会收到一条错误消息 端口数必须为偶数 但是当我尝试查看以太网设备列表时我只能看到一台设备 我在 vmware 工作站环境下的 Ubuntu 中运行框
  • 使用 Runtime.getRuntime 在 Android 上运行 shell 命令

    我正在开发一个设备管理应用程序 已由制造商签名 我使用它来安装其他应用程序 使用以下适用于 android 9 的 adb shell 命令 cat sdcard Download myfolder newapp apk pm instal
  • 如何重试 Promise 决议 N 次,并在尝试之间有延迟?

    我想要一些 JavaScript 代码将 3 个东西作为参数 返回 Promise 的函数 最大尝试次数 每次尝试之间的延迟 我最终做的是使用for环形 我不想使用递归函数 这样 即使有 50 次尝试 调用堆栈也不会长 50 行 这里是打字