我需要在后端NodeJS中使用axios在Google API上进行大量请求。
但是,当您向他发送请求时,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);
});
});
});
});
promise不会完全等待数组let axiosArray = [];
的结束。许诺只关心第一个循环
for (let i = 12300; i < 12800; i++) {
axiosArray.push(callHttpRequestGoogle(i));
}
由于{catch axiosArray
中检测到拒绝时,通过再次推动.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套件帐户,则将无法运行此脚本。以及您在传统Google开发人员帐户上的凭据。
但是您有什么建议要告诉我,一种替代方法吗?