避免出现错误403配额超过了在Google API上发出多个axios HTTP请求的次数

时间:2018-10-16 09:57:07

标签: javascript node.js google-api axios google-api-nodejs-client

我需要在后端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开发人员帐户上的凭据。

但是您有什么建议要告诉我,一种替代方法吗?

0 个答案:

没有答案