How can you retry after an exception in Javascript when using promises?

前端 未结 3 1161
温柔的废话
温柔的废话 2021-01-12 08:03

I\'m using the Bluebird promise library. I have a chain of promisified functions like the following:

    receiveMessageAsync(params)
    .then(function(data)         


        
相关标签:
3条回答
  • 2021-01-12 08:18

    Here's a sample retry function (not yet tested):

    function retry(maxRetries, fn) {
      return fn().catch(function(err) { 
        if (maxRetries <= 0) {
          throw err;
        }
        return retry(maxRetries - 1, fn); 
      });
    }
    

    The idea is that you can wrap a function that returns a promise with something that will catch and retry on error until running out of retries. So if you're going to retry sendResponseAsync:

    receiveMessageAsync(params)
    .then(function(data)) {
        return [data, handleMessageAsync(request)];
    })
    .spread(function(data, response) {
        return [response, deleteMessageAsync(request)];
    })
    .spread(function(response, data) {
        return retry(3, function () { return sendResponseAsync(response); });
    })
    .then(function(data) {
        return waitForMessage(data);
    })
    .catch (function(err) {
       // handle error here
    });
    

    Since the retry promise won't actually throw until all retries have been exhausted, your call chain can continue.

    Edit:

    Of course, you could always loop forever if you preferred:

    function retryForever(fn) {
      return fn().catch(function(err) { 
        return retryForever(fn); 
      });
    }
    
    0 讨论(0)
  • 2021-01-12 08:24

    I just released https://github.com/zyklus/promise-repeat, which retries a promise until it either times out or a maximum number of attempts are hit. It allows you to write:

    receiveMessageAsync(params)
    ...
    .spread(retry(
        function(response, data) {
            return sendResponseAsync(response);
        }
    ))
    ...
    
    0 讨论(0)
  • 2021-01-12 08:28

    Here is a small helper that acts like then but retries the function.

    Promise.prototype.retry = function retry(onFulfilled, onRejected, n){
        n = n || 3; // default to 3 retries
        return this.then(function(result) {
             return Promise.try(function(){ 
                 return onFulfilled(result); // guard against synchronous errors too
             }).catch(function(err){
                 if(n <= 0) throw err;
                 return this.retry(onFulfilled, onRejected, n - 1);
             }.bind(this)); // keep `this` value
        }.bind(this), onRejected);
    };
    

    Which would let you write your code prettier like:

    receiveMessageAsync(params)
    .then(function(data)) {
        return [data, handleMessageAsync(request)];
    })
    .spread(function(data, response) {
        return [response, deleteMessageAsync(request)];
    })
    .retry(function(response, data) {
        return sendResponseAsync(response); // will retry this 3 times
    })
    .then(function(data) {
        return waitForMessage(data);
    })
    .catch (function(err) {
       // I don't like catch alls :/ Consider using `.error` instead.
    });
    
    0 讨论(0)
提交回复
热议问题