Reputation: 11
I'm using ES6 within node.js. Long story short, I only now about callbacks and want to replace them with promises.
I made a test project to get an oauth2 token from an api/endpoint, refresh it and finally revoke it. The goal is, to give the response of the previous request to the next. My code looks like this:
const oauth2Adapter = require('./api/adapter/oauth2Adapter')
function test () {
oauth2Adapter.RequestNewAccessToken()
.then(function (response) {
console.log(response)
return oauth2Adapter.RefreshAccessToken(response.body)
})
.then(function (response) {
return oauth2Adapter.RevokeAccessToken(response.body)
})
.then(console.log)
.catch(console.log)
}
test()
The first promise returns it's response. The next step is now to give it to the second promise as a parameter. But the second promise only receives an undefined object.
I'm a second year cs apprentice, any critic helps me and is appreciated.
Edit: adding the 'return' keyword didn't change the situation. The problem is that 'RefreshAccessToken' 'undefined' receives. Also I don't know if this helps, but here is the 'oauth2Adapter.js' code:
const Promise = require('promise')
const rp = require('request-promise')
const credentials = require('../../misc/credentials/Staging')
function RequestNewAccessToken () {
try {
const response = rp({
method: 'POST',
url: `${credentials.baseUrl}/oauth/token`,
form: {
client_id: credentials.apiKey,
client_secret: credentials.apiSecret,
username: credentials.username,
password: credentials.password,
grant_type: credentials.grantType
},
json: true
})
return Promise.resolve(response)
} catch (error) {
return Promise.reject(error)
}
}
function RefreshAccessToken (token) {
try {
const response = rp({
method: 'POST',
url: `${credentials.baseUrl}/oauth/token`,
form: {
client_id: credentials.apiKey,
client_secret: credentials.apiSecret,
grant_type: 'refresh_token',
refresh_token: token.refresh_token
},
json: true
})
return Promise.resolve(response)
} catch (error) {
return Promise.reject(error)
}
}
function RevokeAccessToken (token) {
try {
const response = rp({
method: 'POST',
url: `${credentials.baseUrl}/oauth/revoke`,
form: {
client_id: credentials.apiKey,
client_secret: credentials.apiSecret,
token: token.access_token
},
json: true
})
return Promise.resolve(response)
} catch (error) {
return Promise.reject(error)
}
}
module.exports = { RequestNewAccessToken, RefreshAccessToken, RevokeAccessToken }
If I execute the code, i get the following text by stdout:
Debugger attached.
{ access_token: '31744bf03a2fb92edb67fcbeead14f4ed8c540843c2439179a54b6439dc94c0e',
token_type: 'Bearer',
expires_in: 660,
refresh_token: 'e53642c69bd0ad954d886dad7a437f88c8c269ecacf2cdcfebc8af1a2d0d9b1e',
created_at: 1538471914 }
TypeError: Cannot read property 'refresh_token' of undefined
at Object.RefreshAccessToken (/Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/api/adapter/oauth2Adapter.js:28:28)
at /Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/Main.js:7:28
at tryCatcher (/Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/node_modules/bluebird/js/release/promise.js:694:18)
at _drainQueueStep (/Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/node_modules/bluebird/js/release/async.js:138:12)
at _drainQueue (/Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/node_modules/bluebird/js/release/async.js:131:9)
at Async._drainQueues (/Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/node_modules/bluebird/js/release/async.js:147:5)
at Immediate.Async.drainQueues (/Users/quest1onmark/coding_stuff/nodejs/EdgeDeviceAdministration/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:810:20)
at tryOnImmediate (timers.js:768:5)
at processImmediate [as _immediateCallback] (timers.js:745:5)
Waiting for the debugger to disconnect...
Process finished with exit code 0
Upvotes: 0
Views: 1528
Reputation: 1
Your second code block is not using promises at all well
try the following instead
const Promise = require('promise')
const rp = require('request-promise')
const credentials = require('../../misc/credentials/Staging')
function RequestNewAccessToken () {
return rp({
method: 'POST',
url: `${credentials.baseUrl}/oauth/token`,
form: {
client_id: credentials.apiKey,
client_secret: credentials.apiSecret,
username: credentials.username,
password: credentials.password,
grant_type: credentials.grantType
},
json: true
});
}
function RefreshAccessToken (token) {
return rp({
method: 'POST',
url: `${credentials.baseUrl}/oauth/token`,
form: {
client_id: credentials.apiKey,
client_secret: credentials.apiSecret,
grant_type: 'refresh_token',
refresh_token: token.refresh_token
},
json: true
});
}
function RevokeAccessToken (token) {
return rp({
method: 'POST',
url: `${credentials.baseUrl}/oauth/revoke`,
form: {
client_id: credentials.apiKey,
client_secret: credentials.apiSecret,
token: token.access_token
},
json: true
});
}
module.exports = { RequestNewAccessToken, RefreshAccessToken, RevokeAccessToken }
As for your code that USES this - you console.log(response)
which has the required format, but then you oauth2Adapter.RefreshAccessToken(response.body)
... response has no body!
So, simply do:
const oauth2Adapter = require('./api/adapter/oauth2Adapter')
function test () {
return oauth2Adapter.RequestNewAccessToken()
.then(response => oauth2Adapter.RefreshAccessToken(response))
.then(response => oauth2Adapter.RevokeAccessToken(response))
.then(console.log)
.catch(console.log)
}
test()
but, since you pass response
straight to the next function without any processing, you can also do
const oauth2Adapter = require('./api/adapter/oauth2Adapter')
function test () {
return oauth2Adapter.RequestNewAccessToken()
.then(oauth2Adapter.RefreshAccessToken)
.then(oauth2Adapter.RevokeAccessToken)
.then(console.log)
.catch(console.log)
}
test()
Upvotes: 0
Reputation: 222369
Promises should be properly chained. This means that then
and catch
callbacks should return a promise to chain, in case there's one.
Also, response
parameter is parsed response body when json: true
is used. If a server responds with token object, then it should be passed as an argument to the function that expects it:
...
.then(function (response) {
console.log(response)
return oauth2Adapter.RefreshAccessToken(response)
})
...
Upvotes: 0
Reputation: 540
Promises are chained by returning another Promise at the end of the then
block. It looks like you didn't call return
properly in the first then
block. You should correct that as follows:
oauth2Adapter.RequestNewAccessToken()
.then(function (requestReponse) {
console.log(response)
return oauth2Adapter.RefreshAccessToken()
})
.then(function (refreshResponse) {
return oauth2Adapter.RevokeAccessToken(JSON.parse(refreshResponse.body))
})
As a sidenote, I like to name my callback args differently with each Promise return, which will help to keep things clean!
Upvotes: 1