【问题标题】:NodeJS Promises not resettingNodeJS承诺不会重置
【发布时间】:2017-12-18 22:34:38
【问题描述】:

如果 API 请求失败,我会使用 Promise 重试 API 请求。我是这样使用它的:

var promise = new Promise((resolve, reject) => {
    client.ApiRequest(params, function(data) {
        if (!Array.isArray(data)) {
            console.log("There was an error with the request.");
            reject("Rate Limit Exceeded");
            return;
        }
        ...
        resolve();
    });
});
Utils.retry(promise, 1500);

然后Utils.retry方法如下:

static delay(delayMS) {
    return new Promise(function(resolve, reject){
        setTimeout(resolve, delayMS);
    });
}

static retry(operation, delayMS) {
    return operation.catch((err) => {
        console.log(err);
        return Utils.delay(delayMS).then(function(){
            return Utils.retry(operation, delayMS)
        });
    });
}

如您所见,它从 Promise 中捕获 reject() 并使用 delay() 在重试之前等待。代码运行了,但是一旦promise一直停留在rejected状态,它似乎就失败了。

例如,当它失败时,它会延迟,然后重试 promise 以输出相同的拒绝消息。但是,在第一个函数中,它不会在后续重试时打印出“请求出现错误”消息,所以我认为它甚至不会重试。

有没有办法重置这个promise状态,以便它在重试时执行promise函数中的所有代码?

【问题讨论】:

  • 这些实用方法是你写的吗? (即你需要坚持他们吗?)另外,为了直截了当地回答你问题的最后一部分,你不能改变承诺的状态。一旦它被解决/拒绝,它就是最终的。
  • @GovindRai 我是根据之前没有使用承诺的答案在这里编写的,但是 .catch() 一直在普通函数上抛出错误,所以我修改它以像这样运行。这是目前唯一使用重试实用程序函数的函数,因此更改它不是什么大问题。
  • 承诺不是操作。这是一个结果。
  • 为什么你的Utilsclass?你几乎不想实例化它,对吗?
  • @Bergi Utils 是一组静态函数,它们封装在一个类中以提高可读性/只需要一个模块导出。我从不实例化它;只需包含它。

标签: javascript node.js es6-promise


【解决方案1】:

不要传递对原始承诺的引用。 每次都传递一个新的承诺。您可以这样做。

// a function that returns a new promise
var createPromise = function() {
    return new Promise((resolve, reject) => {
        client.ApiRequest(params, function(data) {
            if (!Array.isArray(data)) {
                console.log("There was an error with the request.");
                reject("Rate Limit Exceeded");
                return;
            }
            ...
            resolve();
        });
    });
}    

-

static delay(delayMS) {
    return new Promise(function(resolve, reject){
        setTimeout(resolve, delayMS);
    });
}

static retry(operation, delayMS) {
    return operation().catch((err) => { //invoke the promise function
        console.log(err);
        return Utils.delay(delayMS).then(function(){
            return Utils.retry(operation, delayMS)
        });
    });
}

Utils.retry(promise, 1500);

【讨论】:

  • 您可能应该重命名该函数
【解决方案2】:

它给你相同的结果,因为你传递了相同的,已经被拒绝的,承诺返回给你的重试处理程序。您需要创建一个新的 Promise 以返回给重试处理程序以使其正常工作。

这意味着您可能需要修改重试处理程序以接受一个承诺工厂(一个返回您想要的承诺的函数),而不是承诺本身。所以你可以像这样修改你的代码:

// Make function to return this promise instead:
var makePromise = () => {
    return new Promise((resolve, reject) => {
        client.ApiRequest(params, function(data) {
            if (!Array.isArray(data)) {
                console.log("There was an error with the request.");
                reject("Rate Limit Exceeded");
                return;
            }
            ...
            resolve();
        });
    });
};

Utils.retry(makePromise, 1500);

-

static delay(delayMS) {
    return new Promise(function(resolve, reject){
        setTimeout(resolve, delayMS);
    });
}

static retry(operation, delayMS) {
    // Note the () after operation. This function now expects operation
    // to be a function that returns a promise.
    return operation().catch((err) => {
        console.log(err);
        return Utils.delay(delayMS).then(function(){
            return Utils.retry(operation, delayMS)
        });
    });
}

【讨论】:

    猜你喜欢
    • 2021-11-04
    • 2020-07-22
    • 2022-12-04
    • 1970-01-01
    • 2017-10-24
    • 2019-09-29
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    相关资源
    最近更新 更多