Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retry promise himself after fail in node js

I would like to retry my request in a promise. I would like launch my refresh if I have always an 401 error as a loop : (if I have 401 loop on refresh until 200)

I tried with this :

const request = require('request');
let conf    = require('../conf');

let core_service = require('coreService');

let self = module.exports = {
    get_count_questions: function() {
        return new Promise((resolve, reject) => {
            request({
                method: 'GET',
                uri: 'http://api/count-questions',
                auth: {
                    'bearer': conf.token
                },
                json: true
            }, function (error, response, body) {
                if (!error && response.statusCode === 200) {
                    resolve(body);
                } else if (!error && response.statusCode === 401) {
                    core_service.refreshToken().then((data) => {
                        console.log('token refresh');
                        return self.get_count_questions();
                    })
                } else {
                    reject(error);
                }
            })
        });
    }
};

I tried with just 'self.get_count_questions();' without return, but it's not work. I have not error message, just my app freeze.

I see in my console.log "token refresh", but after my app freeze...

Edit

I modified with this, It's like better but the refresh token it's very slow. Just before 401, my app stop, and after about 1 minutes 40 seconds, run:

else if (!error && response.statusCode === 401) {
    console.log('need refresh token');
    core_service.refreshToken()
                .then((response) => {
                    console.log(response);
                    resolve(self.get_count_questions())
                } );
}

My refreshToken function :

refreshToken: function () {
    return new Promise((resolve, reject) => {
        request({
            method: 'GET',
            uri   : 'http://api/refresh',
            auth  : {
                'bearer': conf.token
            },
            json  : true
        }, function (error, response, body) {
            console.log('=====> refresh token <======');
            conf.token = body.data;
            console.log('new Token');
            console.log('=====> end refresh token <======');
            if (!error && response.statusCode === 200) {
                resolve('Refresh token successful');
            } else {
                reject('Error refresh');
            }
        })
    });
}

enter image description here

If I refresh my token on each request, I have a problem :

if (!error && response.statusCode === 200) {
     core_service.refreshToken().then((data)=> {
         resolve(body);
     });

}

enter image description here

like image 336
Jérémie Chazelle Avatar asked Sep 08 '17 13:09

Jérémie Chazelle


People also ask

How do I retry failed Promise?

To retry the promise we have to call the same function recursively with reduced max tries, if the promise failed that is in the catch block. Check if there is a number of tries left then recursively call the same function or else reject with the final error.

What happens if Promise is not resolved?

So failing to resolve or reject a promise just fails to ever change the state from "pending" to anything else. This doesn't cause any fundamental problem in Javascript because a promise is just a regular Javascript object.

Does Promise need return?

There is no need to use a return statement inside a new Promise() callback. The Promise constructor is not expecting any sort of return value from the callback. So, the reason to use a return statement inside that callback is only to control the flow of execution in that function.

Does Promise allSettled run in parallel?

allSettled(promises) is a helper function that runs promises in parallel and aggregates the settled statuses (either fulfilled or rejected) into a result array.


3 Answers

You have to resolve the returned promise. When you resolve using a promise, you basically say, complete this promise with the result of that promise.

var prom = function() {
  return new Promise((resolve, reject) => {
    console.log('request start')
    setTimeout(() => {
      console.log('request finish')
      let ran = Math.random();

      if (ran < 0.1)
        resolve('success');

      else if (ran >= 0.1 && ran < 0.98)
        setTimeout(() => {
          console.log('retry');
          resolve(prom());
        }, 500);

      else
        reject('error');

    }, 500);
  });
};

prom().then(console.log.bind(console), console.log.bind(console));

So you should update your else if block like this:

else if (!error && response.statusCode === 401) {
  console.log('need refresh token');
  core_service.refreshToken()
    .then(() => resolve(self.get_count_questions()));
} 
like image 153
Gokhan Kurt Avatar answered Nov 01 '22 04:11

Gokhan Kurt


Now you almost have it.

However:

return core_service.refreshToken()
                   .then(self.get_count_questions);

You're returning that to the request() callback; that return value is not used.

Instead, you need to resolve your original promise to the new promise from then(), by passing it to your original resolve() function:

resolve(core_service.refreshToken().then(...));
like image 27
SLaks Avatar answered Nov 01 '22 06:11

SLaks


I know that is not optimal solution but it might helps

const request = require('request');
    let conf    = require('../conf');

    let core_service = require('coreService');

    let self = module.exports = {
        get_count_questions: function() {
            return new Promise((resolve, reject) => {
                request({
                    method: 'GET',
                    uri: 'http://api/count-questions',
                    auth: {
                        'bearer': conf.token
                    },
                    json: true
                }, function (error, response, body) {
             try{
                    if (!error && response.statusCode === 200) {
                        resolve(body);
                    } else if (!error && response.statusCode === 401) {
                       throw new Error(response.statusCode);
                    } else {
                        reject(error);
                    }
                 }catch(exc){if(exc === 401){
                            core_service.refreshToken().then((data) => {
                            console.log('token refresh');
                            return self.get_count_questions();
                        })      
                       }

                    }       
                })
            });
        }
    };
like image 1
Atul Agrawal Avatar answered Nov 01 '22 04:11

Atul Agrawal