等待异步方法保留以前的重试有效负载

时间:2017-11-23 22:55:39

标签: node.js promise async-await

在我们的程序中,我们尝试使用await实现任务重试模式。

我们的主要问题是我们的方法在后续版本中保留第一个重试有效负载。

这是重试方法:

async retryTaskUntilExpectedValue({
    task,
    expectedValue,
    messageOnError = 'Max retry number reached without expected result',
    maxRetries = 10,
    timeout = 10,
    spinner = null
  }) {
    let printFn = console.log;
    if (spinner !== null) {
      printFn = spinner.text;
    }

    // Proceed retries
    for (let i = 1; i <= maxRetries; i++) {
      try {
        let result = await task;

        console.log(result); // Always display same result: {"state": "upgrading"} even if curling returns {"state": "upgraded"} after about 2 retries

        result = JSON.parse(result).state;

        if (result === expectedValue) {
          return Promise.resolve(result);
        } else if (i <= maxRetries) {
          printFn(`Result "${result}" differs from expected value "${expectedValue}"`);
          await wait(1000);

          printFn(`Waiting ${timeout}s before retry`);
          await wait(timeout * 1000);

          printFn(`Retrying (${i})`);
          continue;
        } else {
          return Promise.reject(`ERROR: ${messageOnError}`);
        }
      } catch (err) {
        return Promise.reject(`ERROR: Unexpected error while running task`);
      }
    }
};

在我们的CLI中使用:

checkUpgrade(url) {
    return retryTaskUntilExpectedValue({
      task: this.makeHttpRequest('GET', url),
      expectedValue: 'upgraded'
    });
}

在我们的例子中,任务是从我们的后端数据库返回状态的http请求。

模型很简单: { "state": "upgrading" }然后当后端作业完成时,它返回{ "state": "upgraded"}

这项工作需要一些时间来处理(大约20秒)。在我们的测试中,发生了这种情况:

  • 第一个电话:upgrading
  • 首次重试:upgrading
  • 之后,通过手动直接卷曲REST api,我得到了upgraded status
  • CLI中的所有其他重试:upgrading

因此,在我们构建的CLI中,结果为10倍Result "upgrading" differs from expected value "upgraded"

似乎后续重试中的let response = await task;在每次重试时都不会调用任务方法。实际上,如果进行实际调用,它肯定会检索正确的升级状态,因为我们通过卷曲。

如何让await task;实际触发调用任务方法而不是保留第一次调用的结果?

1 个答案:

答案 0 :(得分:2)

承诺是已经开始的操作的结果。通过传入task作为承诺 - 它将始终等待相同的结果并返回相同的值。

相反,retryTaskUntilExpectedValue应该为promise 采用函数并等待对它的调用:

let result = await functionReturningTask();

functionReturningTask首先是您用来获取task的内容。