【问题标题】:Javascript Promises nest deeply just like callbacksJavascript Promise 嵌套很深,就像回调一样
【发布时间】:2018-06-22 18:37:11
【问题描述】:

我正在尝试将 Promises 与我的异步函数一起使用。据我了解,承诺应该减轻回调地狱。 但是,我的代码似乎仍然嵌套得很深。

我是否遗漏了一些关于 Promise 的内容(可以将其重写为更具可读性/惯用语)还是有时像回调一样嵌套 Promise?

在此示例中,我正在构建一个函数,该函数调用 API 以从某个社交媒体帐户中检索朋友列表。如果由于身份验证错误导致初始调用失败,我知道我必须先进行身份验证并再次调用。

const myRequest = { /* custom instance of 'request-promise' */ }

function getFriendsList() {
  return new Promise((resolve, reject) => {
    myRequest.get('/getFriendList').then(resp => {
      if (needsAuthentication(resp)) {
        myRequest.post('/auth', credentials).then(() => {
          myRequest.get('/getFriendList').then(resp => resolve(resp.body))
        }).catch(err => {
          reject(err)
        })
      } else {
        resolve(resp.body)
      }
    }).catch(err => {
      reject(err)
    })
  })
}

function authenticate() {
  return new Promise((resolve, reject) => {
    getCredentials().then(credentials => {
      myRequest.post('/auth').then(resp => {
        return resp.statusCode == '200' ? resolve(resp) : reject(resp)
      })    
    }).catch(err => reject(err))
  })
}

【问题讨论】:

  • 是的,你缺少的是承诺被设计成链式的,而不是嵌套的。将现有 Promise 包装在自己的 Promise 中的方式(使用 new Promise((resolve, reject) => {}))是一种反模式。
  • 具有嵌套承诺的承诺链有时只能被展平。在其他情况下,嵌套可能很重要。

标签: javascript asynchronous callback promise


【解决方案1】:

防止

回调地狱

我们有Promise的方式,但现在要防止

承诺地狱

我们有async/await 语法

你的代码应该是这样的

async function getFriendsList() {
    var resp = await myRequest.get('/getFriendList')
    if (needsAuthentication(resp)) {
        await myRequest.post('/auth', credentials)
        var resp2 = await myRequest.get('/getFriendList')
        return resp2.body
    } else {
        return resp.body
    }
}

async function authenticate() {
    var credentials = await getCredentials()
    var resp = await myRequest.post('/auth')
    return resp
}

请始终记住,异步函数中的任何 Promise.reject() 或任何 throw Error 都会导致函数被拒绝 (Promise)。

所以,在你的 authenticate 函数中

async function authenticate() {
    var credentials = await getCredentials()
    var resp = await myRequest.post('/auth') //If this get rejected
    return resp
}

authenticate().then().catch(error => console.log('error here', error))

永远记得

async 函数只是 Promises,当在其代码中出现拒绝或抛出 Error 时,会使用 return 和 reject 解析。

【讨论】:

    【解决方案2】:

    如果一个 Promise 被一个 Promise 解析,它本身不会解析,而是等待传递的 Promise 解析。所以 Promise 链是扁平的。 同样适用于从 then 链返回 Promise。 这很有用:

    function getFriendsList() {
      return myRequest.get('/getFriendList').then(resp => {
        if (needsAuthentication(resp)) {
          return myRequest.post('/auth', credentials).then(() => 
            myRequest.get('/getFriendList').then(resp => resp.body)
          );         
        } else {
          return resp.body;
        }
      });
    }
    
    function authenticate() {
      return getCredentials()
        .then(credentials => myRequest.post('/auth'))
        .then(resp => {
          if(resp.statusCode == '200'){
            return resp;
          } else {
            throw resp;
          }
        })    
    }
    

    【讨论】:

    • 您可能想要unnest .then(resp => resp.body) 部分
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 1970-01-01
    • 2017-03-22
    • 1970-01-01
    • 2017-11-13
    • 2020-04-13
    • 2015-11-13
    相关资源
    最近更新 更多