Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
590 views
in Technique[技术] by (71.8m points)

asynchronous - In javascript, a function which returns promise and retries the inner async process best practice

I have a function which returns a javascript Promise and inside it there runs some asynchronously code. The async code, needs to be retried for couple of times in cases it fails. I was doing that, till I observed some strange behaviors which made me wonder if I'm doing it right. So I had to change it. Both approaches snipped are down here. I have some idea why the first approach (asyncFunc) doesn't work, I would appreciate if someone could share some technical clarity about it. And for the second approach (ayncFunc_newer) any suggestion on how it can be done better?

var _retryCount = 0;

// this is what I was doing
function asyncFunc () {
return new Promise(function(fulfill, reject) {
doAsync()
.then(fulfill)
.catch(retry);

function retry(promiseResult) {
if(_retryCount < 3) {
_retryCount++;
return asyncFunc();
}
else {
reject(promiseResult);
}
}
});
}

// this what I'm doing now
function ayncFunc_newer() {
    return new Promise(function(fulfill, reject) {
        var retryCount = 0;

        doAsync()
            .then(fulfill)
            .catch(onReject);

        function onReject(bmAuthError) {
            if(retryCount < 3) {
                retryCount++;
                logWarning(error);
                
                doAsync()
                .then(fulfill)
                .catch(onReject);
            }
            else {
                fulfill(false);
            }
        }
    });                 
};
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Best practice is to avoid the promise constructor anti-pattern. Basically, new Promise exists mostly to wrap non-promise APIs, so if your functions already return promises, then there's usually a way to avoid using it.

If you're doing a low fixed number retries, then your case is as simple as:

function ayncFunc() {
  return doAsync().catch(doAsync).catch(doAsync).catch(doAsync);
};

For a configurable number of retries, you'd expand this to:

var retries = 3;

function ayncFunc() {
  var p = doAsync();
  for (var i = 0; i < retries; i++) {
    p = p.catch(doAsync);
  }
  return p;
};

Or for higher number of retries, you could use a recursive approach:

function ayncFunc() {
  function recurse(i) {
    return doAsync().catch(function(e) {
      if (i < retries) {
        return recurse(++i);
      }
      throw e;
    });
  }
  return recurse(0);
};

var console = { log: msg => div.innerHTML += msg + "<br>" };

function doAsync() {
  console.log("doAsync");
  return Promise.reject("Nope");
}

function ayncFunc() {
  return doAsync().catch(doAsync).catch(doAsync).catch(doAsync);
};

var retries = 3;

function ayncFunc2() {
  var p = doAsync();

  for (var i=0; i < retries; i++) {
    p = p.catch(doAsync);
  }
  return p;
};

function ayncFunc3() {
  function recurse(i) {
    return doAsync().catch(function(e) {
      if (i < retries) {
        return recurse(++i);
      }
      throw e;
    });
  }
  return recurse(0);
};

ayncFunc().catch(function(e) { console.log(e); })
.then(ayncFunc2).catch(function(e) { console.log(e); })
.then(ayncFunc3).catch(function(e) { console.log(e); });
<div id="div"></div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...