1

in my application, I have a promised function "serverGet()" which makes a server call. At times, the server returns me an HTTP 200 response but with an empty object. If I try 2 or 3 times, I get the full JSON. Time to find a final solution, I want to create a JS script allowing to re-execute this promised function a number of times until I get the result.

Here is what I developed but unfortunately, it does not return anything on retry 4-3-2-1 :

function promiseWithRetry(fn, retries){

    console.log("retry :"+retries);

    return new Promise(function(resolve, reject) {
        fn.then(function(response){

            if(_.isEmpty(response) && retries > 0){
                console.log("start new retry");
                Promise.resolve(promiseWithRetry(fn, retries-1));

            }else{
                console.log("resolve");
                resolve(response);
            }

        });
    });
}

promiseWithRetry(serverGet(parameters), 5).then(function(response){
  console.log(response)
});

To simulate serverGet(), I have written in jsfiddle a small random function so execute the code several times to test it :

https://jsfiddle.net/christophes/krgvsfcy/

Can you help me ?

Christophe

  • If `fn` was supposed to be a function (and it needs to be!), you need to call it like `fn()`, and also actually pass a function not a promise. – Bergi Mar 25 '20 at 16:45
  • 2
    Also, avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! (Btw, `Promise.resolve(…)` instead of `resolve(…)` never worked) – Bergi Mar 25 '20 at 16:46
  • I would advise you to search for the "iterative promises" (or even "recursive") keywords – imrok Mar 25 '20 at 16:47
  • @Bergi I'm not sure to understand. Can you give me an example ? I can't do `fn().then(function(response){...` – christophes Mar 25 '20 at 17:17
  • I have updated the jsfiddle https://jsfiddle.net/christophes/krgvsfcy/ – christophes Mar 25 '20 at 17:17
  • @christophes Yes, you can and should do exactly that. – Bergi Mar 25 '20 at 17:21
  • @Bergi If I do this, I have the error `Uncaught (in promise) TypeError: fn is not a function` . https://jsfiddle.net/christophes/krgvsfcy/7/ – christophes Mar 25 '20 at 17:22
  • As I said, you need to "*actually pass a function not a promise*". – Bergi Mar 25 '20 at 17:27
  • @Bergi Ok, but in my case I have not the choice. The serverGet function is a part of an API and is a promise. Do you have another idea? – christophes Mar 25 '20 at 17:30
  • No, it's a function that returns a promise. Don't call it, pass a function that calls it. `function doCall() { return serverGet(parameters); } promiseWithRetry(doCall, 5)` or alternatively `promiseWithRetry(() => serverGet(parameters), 5)` – Bergi Mar 25 '20 at 17:32
  • @christophes I updated your jsfiddle with an example; https://jsfiddle.net/79g4nmxe/1/. I hope it's useful for you, I added some comments as well so you may understand better how `.then` and `.catch` works. – JiFus Mar 25 '20 at 17:43
  • Thanks @JiFus ! I love this code. It's more clear to use try/catch. But there is still a bug. When we have an error, the retry are restarted but it do not call back the server. I added "BAD response" and "GOOD response" logs and as you can see in my test, I never have any answer if there is more than 1 retry https://jsfiddle.net/christophes/7r3sk58b/13/ – christophes Mar 26 '20 at 09:03
  • Hi @christophes. This is because we're still passing the promise of the response to the server by reference. If you want the randomness to be recalculated every time, you need to pass the generator function `serverGet` instead of the promise we get as a result from calling `serverGet`. Check the updated fiddle to see what I mean; https://jsfiddle.net/2casn6tr/ – JiFus Mar 26 '20 at 12:43
  • OK @JiFus , so if I understand, I've not the choice. If I want to pass parameters, I need to add another argument in my function : `promiseWithRetry(fn, arg, retries)` , like this : https://jsfiddle.net/christophes/7r3sk58b/20/ – christophes Mar 26 '20 at 13:22
  • 1
    Or you could go with some syntactic sugar: https://jsfiddle.net/kj9o1vwL/. Pass the `PromiseWithRetry` function a generator instead that uses the function you wish to call with the arguments. – JiFus Mar 26 '20 at 15:24

0 Answers0