Функция повторения nodejs, если не удалось X раз - PullRequest
1 голос
/ 06 марта 2019

Я хочу, чтобы моя функция выполнялась 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)

Я обещаю ошибочный результат. После этого, если ошибка пуста, тогда все хорошо. в противном случае продолжайте выполнять ту же команду.

Я уверен, что есть более разумный способ сделать это. Любая помощь будет оценена.

Ответы [ 3 ]

4 голосов
/ 06 марта 2019

Я думаю, все функции Aws могут возвращать Promise из коробки, тогда вы можете просто поместить вызов в try/catch:

let triesCounter = 0;
while(triesCounter < 2){
    console.log(`try #${triesCounter}`)
    try {
        await kinesis.putRecord(params).promise();
        break;  // 'return' would work here as well
    } catch (err) {
       console.log(err);
    }
    triesCounter ++;
}
1 голос
/ 07 марта 2019

В функциональном стиле:

...
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;
    }
}
1 голос
/ 06 марта 2019

Сделайте маленький модуль, скажем 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' );
...