Javascript Promises nest deeply just like callbacks
I am trying to use Promises with my async functions. From my understanding promises are supposed to alleviate callback hell. However it seems my code is still very deeply nested.
Am I missing something about promises (could this be rewritten to be more readable/idiomatic) or do promises nest just like callbacks sometimes?
In this example I'm building a function that calls an API to retrieve a friends list from some social media account. If it the initial call fails due to authentication errors, I know I have to authenticate first and do the call again.
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))
})
}
If a Promise is resolved with a Promise, itself does not resolve but rather waits for the passed Promise to resolve. So the Promise chain is flattened. Same applies to returning a Promise from a then
chain. That's quite useful:
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;
}
})
}
To prevent
callback hell
We have the Promise
way, but now to prevent the
Promise hell
We have the async/await
syntax
Your code should be like this
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
}
Always remember that any Promise.reject()
or any throw Error
inside your async function will result in a rejected function (Promise).
So, in your authenticate
function
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))
Always remember
async
functions are just Promises
, that resolve with the return
and reject
when inside its code something reject or throw an Error
上一篇: 承诺如何在这种情况下实施?