【问题标题】:Promise chaining, use result of request for another onePromise 链接,将请求的结果用于另一个
【发布时间】:2019-03-07 09:17:55
【问题描述】:

我在 node.js 中使用 ES6。长话短说,我现在才谈到回调,并想用 Promise 替换它们。

我做了一个测试项目,从 api/endpoint 获取 oauth2 令牌,刷新它并最终撤销它。目标是,将前一个请求的响应提供给下一个请求。我的代码如下所示:

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

第一个承诺返回它的响应。下一步是现在将它作为参数提供给第二个 Promise。但是第二个 promise 只接收一个未定义的对象。

我是一名二年级的 CS 学徒,任何批评者都会帮助我并受到赞赏。

编辑:添加“return”关键字并没有改变这种情况。问题是 'RefreshAccessToken' 'undefined' 收到。另外我不知道这是否有帮助,但这里是 'oauth2Adapter.js' 代码:

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 }

如果我执行代码,我会通过标准输出得到以下文本:

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

【问题讨论】:

  • 我已经完整阅读了the post,它并没有描述我的问题,因为我正确使用了 Promise,据我现在和其他用户报告。

标签: javascript node.js es6-promise


【解决方案1】:

通过在 then 块的末尾返回另一个 Promise 来链接 Promise。看起来您在第一个 then 块中没有正确调用 return。您应该按如下方式更正:

oauth2Adapter.RequestNewAccessToken()
.then(function (requestReponse) {
  console.log(response)
  return oauth2Adapter.RefreshAccessToken()
})
.then(function (refreshResponse) {
  return oauth2Adapter.RevokeAccessToken(JSON.parse(refreshResponse.body))
})

作为旁注,我喜欢为每个 Promise 返回的回调参数命名不同的名称,这将有助于保持干净!

【讨论】:

  • 我在应有的位置添加了“return”关键字,但没有任何改变。你能看一下我所做的编辑并告诉我我是否理解有误吗?对我有很大帮助。
【解决方案2】:

Promise 应该被正确地链接。这意味着 thencatch 回调应该返回一个承诺链,以防万一。

另外,response 参数在使用json: true 时被解析响应正文。如果服务器使用令牌对象进行响应,则应将其作为参数传递给期望它的函数:

...
.then(function (response) {
  console.log(response)
  return oauth2Adapter.RefreshAccessToken(response)
})
...

【讨论】:

  • 我在应有的位置添加了“return”关键字,但没有任何改变。你能看一下我所做的编辑并告诉我我是否理解有误吗?对我有很大帮助。
  • 你仍然错过了oauth2Adapter.RefreshAccessToken()@JonasRaphaelSchultheiss 的回报
  • @JonasRaphaelSchultheiss 我认为没有问题,只是您使用了 try..catch、Promise.resolve 和 Promise.reject,它们在那里不需要(它们不应该引起问题)。可能只是return rp(...)。固定代码似乎不太可能暴露与错误相同的行为。我建议仔细检查您是否正在运行已修复的代码。
  • 我很确定我执行了正确的代码。我会快速重新启动(即使我不希望它在那之后工作,这是最重要的想法)。我在问题中添加了错误消息,但我认为它没有帮助。感谢您的帮助。
  • @JonasRaphaelSchultheiss 我明白了。我误解了 问题是 'RefreshAccessToken' 'undefined' 接收 可能意味着什么。您没有将参数传递给RefreshAccessToken(),而它需要一个令牌。顺便说一句,使用 json: true 时不需要 JSON.parse。这是一个或另一个。
【解决方案3】:

您的第二个代码块根本没有很好地使用承诺

改用以下方法

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 }

至于你的代码使用这个 - 你 console.log(response) 具有所需的格式,但是你 oauth2Adapter.RefreshAccessToken(response.body) ... 响应没有正文!

所以,只需这样做:

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

但是,由于您将response 直接传递给下一个函数而无需任何处理,因此您也可以这样做

const oauth2Adapter = require('./api/adapter/oauth2Adapter')
function test () {
    return oauth2Adapter.RequestNewAccessToken()
    .then(oauth2Adapter.RefreshAccessToken)
    .then(oauth2Adapter.RevokeAccessToken)
    .then(console.log)
    .catch(console.log)
}
test()

【讨论】:

  • RefreshAccesToken 仍会收到“未定义”。我已经添加了错误消息。感谢您的帮助。
  • 当然可以-我没有修复的代码调用return oauth2Adapter.RefreshAccessToken() ...没有参数...应该是什么参数?
  • 是一个错字,在我的代码中看起来像这样 return oauth2Adapter.RefreshAccessToken(response.body)
  • 好的,你是说你仍然没有定义吗?即使通过response.body?这意味着 response.body 是未定义的......这不是我可以解决的问题,因为不知道你在请求中得到了什么
  • 我已经展示了我在第三个代码块中返回的内容。就在错误消息的上方。我真的不明白我做错了什么,我觉得我在浪费你和对方的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-10
  • 2021-04-03
  • 2019-10-28
  • 1970-01-01
  • 2020-04-24
相关资源
最近更新 更多