最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Retry promise himself after fail in node js - Stack Overflow

programmeradmin4浏览0评论

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');
            }
        })
    });
}

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

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

}

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');
            }
        })
    });
}

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

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

}

Share Improve this question edited Sep 12, 2017 at 7:52 Jérémie Chazelle asked Sep 8, 2017 at 13:36 Jérémie ChazelleJérémie Chazelle 1,8185 gold badges35 silver badges75 bronze badges
Add a comment  | 

5 Answers 5

Reset to default 11 +100

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()));
} 

You're making a recursive call, but you're never actually doing anything with its promise. Therefore, your original promise never resolves.

You need to pass the promise from the recursive call (to refreshToken().then()) to resolve().

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(...));

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();
                        })      
                       }

                    }       
                })
            });
        }
    };

You need to call the initial resolve/reject functions after you retried the request:

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');
                        self.get_count_questions().then((data) => {
                          // call initial resolve function
                          resolve(data);
                        }).catch((error) => {
                          // call initial reject function
                          reject(error);
                        });
                    }).catch((error) => {
                        // reject if refreshToken fails
                        reject(error);
                    });
                } else {
                    reject(error);
                }
            })
        });
    }
};

You also have to make sure, that the second call actually resolves/rejects and doesn't land in another 401. Because else you have an infinite recursion.

发布评论

评论列表(0)

  1. 暂无评论