Nodejs - Re-Calling function on error callback - Is there a non blocking way?

♀尐吖头ヾ 提交于 2019-12-04 11:19:44

What I would suggest is that you make a function for your operation. If it fails, you set a short timer and retry after that timer fires. This will give you an asynchronous behavior between retries and other code in the sever can run.

function requestRetry(url, data, retryTimes, retryDelay, callback) {
    var cntr = 0;

    function run() {
        // try your async operation
        request(..., function(err, data) {
            ++cntr;
            if (err) {
                if (cntr >= retryTimes) {
                    // if it fails too many times, just send the error out
                    callback(err);
                } else {
                    // try again after a delay
                    setTimeout(run, retryDelay);
                }
            } else {
                // success, send the data out
                callback(null, data);
            }
        });
    }
    // start our first request
    run();
}


requestRetry(someUrl, someData, 10, 500, function(err, data) {
    if (err) {
        // still failed after 10 retries
    } else {
        // got successful result here
    }
});

This is a fairly simple retry scheme, it just retries on a fixed interval for a fixed number of times. More complicated schemes implement a back-off algorithm where they start with fairly quick retries, but then back-off to a longer period of time between retries after the first few failures to gives the server a better chance of recovering. If there happening to be lots and lots of clients all doing rapid retries, then you as soon as your server has a hiccup, you can get an avalanche failure as all the clients suddenly start rapidly retrying which just puts your serve in even more trouble trying to handle all those requests. The back-off algorithm is designed to allow a server a better chance of preventing an avalanche failure and make it easier for it to recover.

The back-off scheme is also more appropriate if you're waiting for the service to come back online after it's been down a little while.

For retry http call when it come with error. but first you need to check this error be retry-able or not.

RETRIABLE_NETWORK_ERRORS = ['ECONNRESET', 'ENOTFOUND', 'ESOCKETTIMEDOUT', 'ETIMEDOUT', 'ECONNREFUSED', 'EHOSTUNREACH', 'EPIPE', 'EAI_AGAIN'];

If error comes under RETRIABLE_NETWORK_ERRORS than you need to come under retry logic otherwise mark as error.

For retry logic use exponential backoff algorithm. you follow https://developers.google.com/api-client-library/java/google-http-java-client/backoff

const _ = require('lodash');
const request = require('request');

var httpArray = getHttpReq(); //return array

function makeHttpRequest() {
    _.each(httpArray, function (httpRequest) {
        retryRequest(httpRequest);
    });
}

function retryRequest(httpRequest) {

    const MAX_RETRY = 2;
    var retryCnt = 0;
    Retry();

    function Retry() {

        request(httpRequest, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                console.log(body)
            }
            else {
                if (retryCnt < MAX_RETRY) {
                    retryCnt += 1;
                    var currRetryIntervalMs = (1 << retryCnt) * 1000; //exponential back off logic
                    setTimeout(Retry, currRetryIntervalMs);
                }
                else {
                    console.log('http fail');
                }
            }
        });
    }
}

Here is an asynchronous loop

function asyncLoop(i, range, callback) {
    var results = 0;
    if(i < range) {
        // do something, update results
        aysncLoop(i+1, range, callback); 
    } else {
        callback(null, results)
    }
}

To loop it 10 times, call it as follows

asyncLoop(0, 10, function(err, results) {
    console.log(results);
});

Pass your error condition in place of range and check it inside the loop. Hope this will help you

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!