Мне нужно сделать большой цикл запросов в Google API с помощью axios в моем внутреннем NodeJS.
Но Google API блокируется в определенное время с ошибкой 403, когда вы заполняете его запросами.Как сказано в документации, нам нужно использовать метод экспоненциального отката https://developers.google.com/admin-sdk/directory/v1/limits
Повторить с использованием экспоненциального отката.Вам нужно замедлить скорость, с которой вы отправляете запросы.
Поток для реализации простого экспоненциального отката следующий:
Make a request to the API
Receive an error response that has a retry-able error code
Wait 1s + random_number_milliseconds seconds
Retry request
Receive an error response that has a retry-able error code
Wait 2s + random_number_milliseconds seconds
Retry request
Receive an error response that has a retry-able error code
Wait 4s + random_number_milliseconds seconds
Retry request
Receive an error response that has a retry-able error code
Wait 8s + random_number_milliseconds seconds
Retry request
Receive an error response that has a retry-able error code
Wait 16s + random_number_milliseconds seconds
Retry request
If you still get an error, stop and log the error.
Мой код ниже
const router = require("express").Router();
const axios = require("axios");
const { google } = require("googleapis");
const scopeGooleAPI = [
"https://www.googleapis.com/auth/admin.directory.group.readonly",
"https://www.googleapis.com/auth/admin.directory.group.member.readonly",
"https://www.googleapis.com/auth/admin.directory.user.readonly",
"https://www.googleapis.com/auth/admin.directory.resource.calendar",
"https://www.googleapis.com/auth/calendar"
];
var clientGoogleAPI = new google.auth.JWT(
client_email,
null,
private_key,
scopeGooleAPI,
"admin@admin.com"
);
router.post("/insertResourceHTTP", (req, res) => {
if (!clientGoogleAPI)
return res
.status(500)
.json("Google G Suite Credentials have not been found in the .env file");
return clientGoogleAPI.authorize((err, tokens) => {
if (err) return res.status(500).json(err);
let config = {
headers: { Authorization: "Bearer " + tokens.access_token }
};
let axiosArray = [];
function callHttpRequestGoogle(i, s = 1) {
return axios
.post(
"https://www.googleapis.com/admin/directory/v1/customer/my_customer/resources/calendars",
{
//json : true,
resourceId: "resourceIdPromise" + i, // required
resourceName: "resourceNamePromise" + i, // required
// buildingId: "",
// capacity: 0,
// etags: "",
// floorName: "",
// floorSection: "",
generatedResourceName: "generatedResourceNamePromise" + i,
kind: "admin#directory#resources#calendars#CalendarResource",
resourceCategory: "OTHER",
resourceDescription: "resourceDescription",
resourceEmail: "resourceEmail",
resourceType: "resourceType",
userVisibleDescription: "userVisibleDescription"
},
config
)
.then(responseCatched => {
return { responseCatched: responseCatched };
})
.catch(errorCatched => {
if (errorCatched.response.data.error.code === 403) {
console.log(errorCatched.response.data.error.code, s, i);
s += 1;
return axiosArray.push(
setTimeout(() => {
callHttpRequestGoogle(i, s);
}, s * 1000)
);
}
return { errorCatched: errorCatched };
});
}
for (let i = 12300; i < 12800; i++) {
axiosArray.push(callHttpRequestGoogle(i));
}
Promise.all(axiosArray).then(OKK => {
console.log("Array completed");
axios
.all(axiosArray)
.then(
axios.spread((...argsResponse) => {
let responseArray = [];
for (let i = 0; i < argsResponse.length; i++) {
// 3 cases : There is an error, there is no error, or there is an unknown error
if (argsResponse[i].hasOwnProperty("errorCatched")) {
responseArray.push({
return: argsResponse[i].errorCatched.response.data.error,
data: JSON.parse(
argsResponse[i].errorCatched.response.config.data
)
});
} else if (argsResponse[i].hasOwnProperty("responseCatched")) {
responseArray.push({
return: "Item well added statusCode 200",
data: argsResponse[i].responseCatched.data
});
} else {
responseArray.push({
return: "unknown error, sorry about that"
});
}
}
res.status(200).json(responseArray);
})
)
.catch(err => {
res.status(500).json(err.message);
});
});
});
});
Обещание не дожидается завершения конца массива let axiosArray = [];
.Обещание относится только к первому циклу
for (let i = 12300; i < 12800; i++) {
axiosArray.push(callHttpRequestGoogle(i));
}
Поскольку axiosArray
подается во второй раз путем повторного нажатия, когда в .catch .catch(errorCatched => {})
было обнаружено отклонениепроблема в том, что эта строка console.log("Array completed");
выполняется и, как следствие, также res.status(200).json(responseArray);
, которая выходит из сценария.
Я вижу, что он все еще работает в фоновом режиме, потому что console.log(errorCatched.response.data.error.code, s, i);
возвращаются и иногда даже увеличиваются до 10 секунд.
axiosArray.push(
setTimeout(() => {
callHttpRequestGoogle(i, s);
}, s * 1000)
);
Вы не сможете запустить этосценарий, если у вас нет учетной записи Google G Suite.А также ваши собственные учетные данные в классической учетной записи разработчика Google.
Но есть ли у вас какие-либо предложения, чтобы сказать мне, альтернатива?