So I am working with promises and async/await for the first time. From my understanding async makes a function asynchronous and allows other functions to be executed while it awaits a response from a query etc. We were given the following code as an example and asked to describe in which order it executes:
const axios = require("axios");
const contributorCount = (repositories, contributorsList) => {
let repositoryContributorCount = [];
for (let i = 0; i < repositories.length; i ) {
repositoryContributorCount.push({
name: repositories[i].name,
numberOfContributors: contributorsList[i].length,
});
}
return repositoryContributorCount;
};
const getRepoContributors = async (repo) => {
const contributorsReponse = await axios.get(repo.contributors_url);
return await contributorsReponse.data;
};
const getAllRepos = (repos) => {
const newRepos = repos.slice(0, 5);
return Promise.all(newRepos.map(getRepoContributors)).then((contributors) => {
return contributorCount(newRepos, contributors);
});
};
function listRepoContributorCounts() {
axios
.get("https://api.github.com/orgs/wesabe/repos")
.then((response) => response.data)
.then(getAllRepos)
.then((repositoryContributorCounts) => {
return repositoryContributorCounts;
})
.catch((error) => {
return error;
});
}
By my understanding, in the 2nd function we're assigning an async function to getRepoContributors and that function waits to get a response from the given url. While it's waiting for the response it allows the rest of the code to execute. But why is there a second await for the return statement? Shouldn't you only need the first since the return statement would only execute after the data is retrieved? Also what would be the exact order these functions execute in? 1-4 or 4-1 etc? Really appreciate all the help, promises are the most confusing thing I've ran into in terms of JS so far but I feel like I have decent basic understanding of it. Async/await is complicating things for me further tho
I was also given a 2nd code excerpt which is pretty similar to above and asked to describe the order of execution again.
const axios = require("axios");
const contributorCount = (repositories, contributorsList) => {
return repositories.map((repository, position) => {
return {
name: repository.name,
numberOfContributors: contributorsList[position].length,
};
});
};
const getRepositoryContributors = async (repository) => {
const contributorsResponse = await axios.get(repository.contributors_url);
return await contributorsResponse.data;
};
const getRepositories = (repositories, upToIndex) => {
const repositoriesCopy = repositories.slice(0, upToIndex);
return Promise.all(repositoriesCopy.map(getRepositoryContributors)).then(
(contributors) => {
return contributorCount(repositoriesCopy, contributors);
}
);
};
const getOrganizationInfo = async (organizations) => {
const organizationRepositories = await axios.get(organizations[2].repos_url);
return organizationRepositories.data;
};
function findOrganizationInfo() {
axios
.get("https://api.github.com/organizations")
.then((response) => response.data)
.then(getOrganizationInfo)
.then((repositories) => getRepositories(repositories, 5))
.then((repositoryContributorCounts) => {
console.log(repositoryContributorCounts);
})
.catch((error) => {
console.log(error);
});
}
CodePudding user response:
async
doesn't make a function asynchronous. It does two things:
- Wrap the body of the function in a
Promise
and return that promise; this allows callers to use.then()
orawait
to get the result of the function. - Allow the use of
await
inside the function.
The function is actually asynchronous if it calls other asynchronous functions; in this example, axios.get()
is async.
await
allows you to call an async function that returns a promise as if your code is sequential. But it only makes the code within the calling function sequential-like; the function actually returns the promise immediately, and other code that doesn't wait for it can proceed. This keeps the application from locking up while the async operation is taking place.
But since all the code in your example uses either await
or .then()
, it's mostly sequential within this context.
listRepoContributorCounts()
calls axios.get()
and uses .then()
to wait for its response.
After getting the response, it calls getAllRepos()
with the array from response.data
.
getAllRepos()
calls newRepos.map(getRepoContributors)
.
Each of the calls to getRepoContributors()
performs an axios.get()
call, which is asynchronous, and returns its promise. So these AJAX requests run concurrently.
Then it calls Promise.all()
on this array of promises, which makes it wait for all of them to complete. The array of values that are returned will be passed to the anonymous function
(contributors) => {
return contributorCount(newRepos, contributors);
}
This simply combines the array of repos with the returned contributor data. contributorCount()
is an ordinary, synchronous function.
This final code:
.then((repositoryContributorCounts) => {
return repositoryContributorCounts;
})
is totally redundant and unnecessary.