Javascript:使用 setTimeout 重试的函数

Ale*_*exD 5 javascript settimeout node.js promise

我有一个功能downloadItem可能会因网络原因而失败,我希望能够在实际拒绝该项目之前重试几次。重试需要超时,因为如果出现网络问题,则立即重试是没有意义的。

这是我到目前为止所拥有的:

function downloadItemWithRetryAndTimeout(url, retry, failedReason) {
    return new Promise(function(resolve, reject) {
        try {
            if (retry < 0 && failedReason != null) reject(failedReason);

            downloadItem(url);
            resolve();
        } catch (e) {
            setTimeout(function() {
                downloadItemWithRetryAndTimeout(url, retry - 1, e);
            }, 1000);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

显然,这会失败,因为我第二次(以及第二次)打电话时,downloadItemWithRetryAndTimeout我没有按要求返回承诺。

我如何让它与第二个承诺一起正常工作?

PS,如果代码在 NodeJS 中运行很重要。

Ori*_*ori 5

我有两个想法:

将承诺移出迭代函数 downloadItemWithRetryAndTimeout - 现在,resolve() 将可用于所有迭代:

function downloadWrapper(url, retry) {
    return new Promise(function (resolve, reject) {
        function downloadItemWithRetryAndTimeout(url, retry, failedReason) {

            try {
                if (retry < 0 && failedReason != null)
                    reject(failedReason);

                downloadItem(url);
                resolve();
            } catch (e) {
                setTimeout(function () {
                    downloadItemWithRetryAndTimeout(url, retry - 1, e);
                }, 1000);
            }

        }

        downloadItemWithRetryAndTimeout(url, retry, null);
    });
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案有效,但它是一种反模式,因为它破坏了承诺链:当每次迭代返回一个承诺时,只需解析该承诺,然后使用 .then 来解析之前的承诺,依此类推:

function downloadItemWithRetryAndTimeout(url, retry, failedReason) {
    return new Promise(function (resolve, reject) {
        try {
            if (retry < 0 && failedReason != null)
                reject(failedReason);

            downloadItem(url);
            resolve();
        } catch (e) {
            setTimeout(function () {
                downloadItemWithRetryAndTimeout(url, retry - 1, e).then(function () {
                    resolve();
                });
            }, 1000);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)