如果X次失败,则nodejs重试功能

时间:2019-03-06 20:38:44

标签: node.js amazon-web-services promise callback async-await

我希望函数执行X(= 3)次直到成功。

在我的情况下,我正在运行kinesis.putRecord(通过AWS API),如果失败了,我想再次运行它直到成功为止,但尝试不超过3次。

我是NodeJS的新手,我写的代码很难闻。

const putRecordsPromise = function(params){
    return new Promise((resolve, reject) => {
        kinesis.putRecord(params, function (err, data) {
            resolve(err)
        });
    })
}

async function waterfall(params){
    try{
        let triesCounter = 0;
        while(triesCounter < 2){
            console.log(`try #${triesCounter}`)
            let recordsAnswer = await putRecordsPromise(params)
            if(!recordsAnswer){
                console.log("success")
                break;
            }
            triesCounter += 1;
        }
        // continue ...

    } catch(err){
        console.error(err)
    }
}

waterfall(params)

我保证会得到错误的结果。之后,如果err为空,则一切正常。否则,请继续运行相同的命令。

我敢肯定有更聪明的方法可以做到这一点。任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:3)

我认为,所有Aws函数都可以立即返回Promise,然后您可以将调用放入responses

IResponseConfig[]

答案 1 :(得分:1)

制作一个小模块,说try-and-try-again.js

exports = module.exports = tryAndTryAgain;

function tryUntilSuccess( maxTries, thisContext , fn, ...argv) {
  let success = false;

  for (let i = i ; i < maxTries && !success ; ++i ) {
    let rc = fn.apply(thisContext, args);
    success = rc == 0 ? true : false;
  }

  return success;
}

然后您可以在任何地方使用它:

const tryAndTryAgain = require('./try-and-try-again');

function somethingThatMightNeedARetry() { ... }

const succeeded = tryAndTryAgain( 3 , null, somethingThatMightNeedARetry, 'arg-1', 'arg-2', 'arg-3' );

答案 2 :(得分:1)

实用风格:

...
await tryUntilSucces(() => kinesis.putRecord(params).promise());
...

async function tryUntilSucces(promiseFn, maxTries=3) {
    try {
        return await promiseFn();
    } catch (e) {
        if (maxTries > 0) {
            return tryUntilSucces(promiseFn, maxTries - 1);
        }
        throw e;
    }
}

答案 3 :(得分:0)

有一个名为 async-retrynpm 包非常方便。它充当您的函数的包装器,并在有任何异常抛出时重试(除了一些您可以处理的异常,请参阅下面的示例)。

// Packages
const retry = require('async-retry')
const fetch = require('node-fetch')
 
await retry(async bail => {
  // if anything throws, we retry
  const res = await fetch('https://google.com')
 
  if (403 === res.status) {
    // don't retry upon 403
    bail(new Error('Unauthorized'))
    return
  }
 
  const data = await res.text()
  return data.substr(0, 500)
}, {
  retries: 5
})