0

I have a method in my service which reads the token from storage and returns a promise.

getToken() {
 return this.storage.get('access_token');
}

(storage.get returns a promise)

I need to modify the above method such that it first read the access token from storage and check its expiry, if its not expired return it immediately, if its expired read refresh_token from storage i.e. this.storage.get('refresh_token') which again returns a promise, after checking if its not expired, I need to make http request using Angular 2 http.post to my api which will return a new access token. Once it receive the new access token the getToken function will return.

I though the below will work, but it doesnt:

getToken() {
        var promise = new Promise(function (resolve, reject) {
            this.storage.get('access_token').then((accessToken) => {
                //check if the token is expired
                if (accessToken) {
                    if (!this.isExpired(accessToken)) {
                        resolve(accessToken);
                    }
                    else {
                        this.storage.get('refresh_token').then((refreshToken) => {
                            if (!this.isExpired(refreshToken)) {
                                this.http.post('/api/refresh/', { token:refreshToken })
                                    .subscribe((data) => {
                                        resolve(data);
                                    });
                            }
                            else {
                                resolve(null);
                            }
                        });
                    }
                } else {
                    resolve(null);
                }
            });
        });

        return promise;
    }

Can anyone please guide, how to achieve this?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Naveed Ahmed
  • 10,048
  • 12
  • 46
  • 85

1 Answers1

2

I bet you have the wrong this in your callback function that you pass to the new Promise constructor.

You could use an arrow function there as well, or you simply avoid the promise construction antipattern and drop it completely:

getToken() {
    return this.storage.get('access_token').then(accessToken => {
        if (!accessToken)
            return null;
        else if (!this.isExpired(accessToken))
            return accessToken;
        else
            return this.storage.get('refresh_token').then(refreshToken => {
                if (this.isExpired(refreshToken))
                     return null;
                else
                     return promiseFromObservable(this.http.post('/api/refresh/', { token:refreshToken }));
            });
    });
}

function promiseFromObservable(o) {
    return new Promise(resolve => o.subscribe(resolve));
}
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thank you so much Bergi, this was really helpful and fixed the error. But now there is one more issue. I need to write the new token received from /api/refresh/ to storage. before promise returns. So I updated the last return call to return this._gs.promiseFromObservable(this.sendPostRequest('/api/refresh/', { token: refreshToken }, options).subscribe((newToken) => { this.storage.set('access_token', newToken); })); but now I am receiving error "EXCEPTION: o.subscribe is not a function" can you please guide? – Naveed Ahmed Dec 14 '16 at 18:15
  • Ok got it fixed, what I have done is subscribed in promiseFromObservable method and put this.storage.set('access_token', newToken); in it. Is it the correct approach? – Naveed Ahmed Dec 14 '16 at 18:39
  • 1
    No, don't subscribe multiple times. Just chain another `then` callback: `return promiseFromObservable(this.sendPostRequest(…)).then(new_Token => { this.storage.set('access_token', newToken); return newToken; });` – Bergi Dec 14 '16 at 19:32
  • Working perfectly! Thank you so much Bergi, really appreciate your help :) – Naveed Ahmed Dec 14 '16 at 21:07