Reputation: 23
I created this function to get list all my drives from GDrive.
async getAllDrives(token) {
let nextPageToken = ""
let resultArray = []
const config= {
headers: {
Authorization: `Bearer ${token}`
}
};
const bodyParams = {
pageSize: 2,
fields: 'nextPageToken, drives(id, name)',
q:`hidden=false`,
};
do {
axios.get(
`https://www.googleapis.com/drive/v3/drives`,
config,
bodyParams,
).then(result => {
nextPageToken = result.data.nextPageToken;
resultArray.push(result.data.drives);
resultArray = resultArray.flat();
console.log("result", resultArray);
}).catch(error => {
console.log(error);
//res.send(error);
});
}while(nextPageToken);
resultArray = resultArray.flat();
resultArray.map(drive => {
drive.isSharedDrive = true;
return drive;
});
return JSON.stringify(resultArray);
}
When I look in console.log
then(result => {
nextPageToken = result.data.nextPageToken;
resultArray.push(result.data.drives);
resultArray = resultArray.flat();
console.log("result", resultArray);
})
I have the expected result,
result [
{
kind: 'drive#drive',
id: '**',
name: ' ★ 🌩'
},
]
but return JSON.stringify(resultArray);
is empty.
I found a similar question here, How do I return the response from an asynchronous call? but the answer is not satisfying.
Upvotes: 0
Views: 1027
Reputation: 173
I recommend you study a little more about async/await.
It makes no sense for you to use async and put a .then().catch()
, the purpose of async to get these encapsulated syntaxes.
async getAllDrives(token) {
try {
const getDrives = await this.request(token)
console.log(getDrives)
const results = this.resultArray(getDrives)
return results
} catch (e) {
console.log(e)
}
}
I didn't quite understand your while or your objective, adapt it to your code or remove it
async request(token) {
let nextPageToken = 1 // ????????
const config = {
headers: {
Authorization: `Bearer ${token}`
}
};
const bodyParams = {
pageSize: 2,
fields: 'nextPageToken, drives(id, name)',
q: `hidden=false`,
};
let getDrives = [];
// loop for each request and create a request array
for (let x = 0; x < fields.nextPageToken; x++) {
const request = axios.get(
`https://www.googleapis.com/drive/v3/drives`,
config,
bodyParams
);
getDrives.push(request)
}
const drives = await Promise.all(getDrives)
return drives
}
async resultArray(drivers) {
// result treatment here
}
The return of promise all will be an array of the driver's responses
Note: The response in request.data
const request = await axios.get()
const resposta = request.data
Read about https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
Upvotes: 0
Reputation: 201553
I believe your goal is as follows.
nextPageToken
in the request, in this case, it is required to run the script with a synchronous process. So, async/await is used. This has already been mentioned in the existing answers.axios.get()
.nextPageToken
, it is required to include the property of pageToken
. In your script, pageToken
is not used. By this, the infinite loop occurs because nextPageToken
is continued to be returned.When these points are reflected in your script, how about the following modification?
let resultArray = [];
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
params: {
pageSize: 2,
fields: "nextPageToken, drives(id, name)",
q: `hidden=false`,
pageToken: "",
},
};
do {
const { data } = await axios
.get(`https://www.googleapis.com/drive/v3/drives`, config)
.catch((error) => {
if (error.response) {
console.log(error.response.status);
console.log(error.response.data);
}
});
if (data.drives.length > 0) {
resultArray = [...resultArray, ...data.drives];
}
nextPageToken = data.nextPageToken;
config.params.pageToken = nextPageToken;
} while (nextPageToken);
resultArray.map((drive) => {
drive.isSharedDrive = true;
return drive;
});
return JSON.stringify(resultArray);
When this script is run, the following result is obtained.
[
{"id":"###","name":"###","isSharedDrive":true},
{"id":"###","name":"###","isSharedDrive":true},
,
,
,
]
From the official document of "Drives: list",
pageSize
: Maximum number of shared drives to return per page. Acceptable values are 1 to 100, inclusive. (Default: 10)
pageSize
is 100, the number of loops can be reduced. If you want to test the loop using nextPageToken
, please reduce the value.Upvotes: 0
Reputation: 525
You used the async call slightly incorrectly. You calling axios.get
without await
keyword, but with .then
chaining. Since you don't wait for result to return, you getting empty array first, returning you nothing. And only then your callback function inside .then
is getting called. To simplify, you doing this in your example:
function getAllDrives() {
// Local variable where you want your result
let result = [];
// You calling the axios.get method, but don't wait for result
axios.get().then(result => {})
// Empty result is getting returned immediately
return result;
}
And when response is returned from the remote server, function inside .then
trying to save result to local variable. But function is already completed, so you don't get anything.
What you actually should do is call axios.get
with await
keyword:
// You should always cover your asynchronous code with a try/catch block
try {
// Instead of `then` callback use `await` keyword. Promise returned from
// this method will contain result. If error occurs, it will be thrown,
// and you can catch it inside `catch`.
const result = await axios.get(
`https://www.googleapis.com/drive/v3/drives`,
config,
bodyParams
);
// Here is your code as you wrote it inside `then` callback
nextPageToken = result.data.nextPageToken;
resultArray.push(result.data.drives);
resultArray = resultArray.flat();
console.log("result", resultArray);
} catch (error) {
// And here is your error handling code as you wrote it inside `catch`
console.log(error);
}
This way your method will not complete until your request is not executed.
You can read more about async/await functions here.
Upvotes: 1