Javascript Promise就像回调一样深深地嵌套

时间:2018-01-13 14:32:36

标签: javascript asynchronous callback promise

我试图在我的异步函数中使用Promises。从我的理解承诺应该缓解回调地狱。 但是看起来我的代码仍然非常嵌套。

我是否遗漏了一些关于承诺的内容(这可能会被重写为更具可读性/惯用性),还是像有时回调一样做承诺?

在此示例中,我正在构建一个函数,该函数调用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))
  })
}

2 个答案:

答案 0 :(得分:1)

如果使用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;
      }
    })    
}

答案 1 :(得分: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,当其代码内部拒绝或抛出return

时,rejectError解析