Дождитесь выполнения дочерних функций перед возвратом - PullRequest
1 голос
/ 19 июня 2019

Итак, у меня есть этот скрипт, который переименовывает файлы на Google Диске. Он читает две колонки из Google Spreadsheet, содержащие fileID и имя файла. Находит файлы с fileId на Google Диске и переименовывает его с именем файла из листа. Все работает нормально. Чтобы сделать его проще и доступнее как маршрут в API, я его экспортировал.

Проблема в том, что основная функция module.exports.rename () имеет все эти дочерние функции, которые выполняются. Он не ждет выполнения и переименования, а просто возвращает ответ. Он просто возвращает сообщение «Переименованы 1 файлы успешно!», Поскольку счетчик ctr изначально равен 1.

Я пытался использовать логическую переменную, установленную как false. Затем установите значение true в getSheetandBatchRename () и добавьте приведенный выше оператор if для основной функции. Но это, конечно, не работает.

Я думаю, что мне здесь чего-то не хватает Как правильно достичь этого?

module.exports.rename = async function(req, res) {
  const fs = require("fs");
  const readline = require("readline");
  const { google } = require("googleapis");

  // If modifying these scopes, delete token.json.
  const SCOPES = [
    "https://www.googleapis.com/auth/drive.metadata",
    "https://www.googleapis.com/auth/spreadsheets.readonly"
  ];
  // The file token.json stores the user's access and refresh tokens, and is
  // created automatically when the authorization flow completes for the first
  // time.
  const PATH = "./server/components/scripts/renamingTool/";
  const TOKEN_PATH = PATH + "token.json";

  let taskDone = false;

  // Load client secrets from a local file.
  fs.readFile(PATH + "credentials.json", (err, content) => {
    if (err) return console.log("Error loading client secret file:", err);
    // Authorize a client with credentials, then call the Google Drive API.
    authorize(JSON.parse(content), getSheetandBatchRename);
  });

  /**
   * Create an OAuth2 client with the given credentials, and then execute the
   * given callback function.
   * @param {Object} credentials The authorization client credentials.
   * @param {function} callback The callback to call with the authorized client.
   */
  function authorize(credentials, callback) {
    const { client_secret, client_id, redirect_uris } = credentials.installed;
    const oAuth2Client = new google.auth.OAuth2(
      client_id,
      client_secret,
      redirect_uris[0]
    );

    // Check if we have previously stored a token.
    fs.readFile(TOKEN_PATH, (err, token) => {
      if (err) return getAccessToken(oAuth2Client, callback);
      oAuth2Client.setCredentials(JSON.parse(token));
      callback(oAuth2Client);
    });
  }

  /**
   * Get and store new token after prompting for user authorization, and then
   * execute the given callback with the authorized OAuth2 client.
   * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
   * @param {getEventsCallback} callback The callback for the authorized client.
   */
  function getAccessToken(oAuth2Client, callback) {
    const authUrl = oAuth2Client.generateAuthUrl({
      access_type: "offline",
      scope: SCOPES
    });
    console.log("Authorize this app by visiting this url:", authUrl);
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout
    });
    rl.question("Enter the code from that page here: ", code => {
      rl.close();
      oAuth2Client.getToken(code, (err, token) => {
        if (err) return console.error("Error retrieving access token", err);
        oAuth2Client.setCredentials(token);
        // Store the token to disk for later program executions
        fs.writeFile(TOKEN_PATH, JSON.stringify(token), err => {
          if (err) return console.error(err);
          console.log("Token stored to", TOKEN_PATH);
        });
        callback(oAuth2Client);
      });
    });
  }

  async function getSheetandBatchRename(auth) {
    try {
      const data = await getSheet(auth);
      console.log("Number of inventories : " + data.length);
      taskDone = true;
    } catch (err) {
      console.log("getSheetandBatchRename");
      console.log(err);
    }
  }

  function updateExt(ext) {
    // to solve if ther were some problems
    if (ext === "1" || ext === "0" || ext === "2" || ext === " Aula 2")
      ext = "jpg";
    return ext;
  }

  function getSheet(auth) {
    const sheets = google.sheets({ version: "v4", auth });
    return new Promise((resolve, reject) => {
      sheets.spreadsheets.values.get(
        {
          spreadsheetId: "1QV3ZshFNVrPCSvMP1O0KjXTcx5pfQMNuNeFbku-TKm4",
          range: "Final!A2:B"
        },
        async (err, res) => {
          if (err) reject(err);
          let data = res.data.values;
          try {
            for (const [i, el] of data.entries()) {
              let filename = await getafile(auth, el[0], i);
              if (filename !== -1) {
                let ext = filename.split(".");
                ext = ext[ext.length - 1];
                // ext = updateExt(ext);
                let newName = el[1] + "." + ext;
                await renameafile(auth, el[0], i, newName);
              }
            }
          } catch (err) {
            console.log("getSheet");
            console.log(err);
            reject(err);
          }
          resolve(data);
        }
      );
    });
  }

  let ctr = 1;
  function getafile(auth, fileId, i) {
    if (fileId === -1) return -1;
    const drive = google.drive({ version: "v3", auth });
    return new Promise((resolve, reject) => {
      drive.files.get(
        {
          fileId: fileId
        },
        (err, res) => {
          if (err) {
            reject(err);
          }
          if (res.status !== 200) {
            reject("Status Code : " + res.status);
          }
          let filename = res.data.name;
          // console.log(ctr + "\t" + fileId + "\t" + filename);
          ctr++;
          resolve(filename);
        }
      );
    });
  }

  function renameafile(auth, fileId, i, newName) {
    const drive = google.drive({ version: "v3", auth });
    return new Promise((resolve, reject) => {
      drive.files.update(
        {
          fileId: fileId,
          resource: {
            name: newName
          }
        },
        (err, res) => {
          if (err) {
            reject(err);
          }
          if (res.status !== 200) {
            reject("Status Code : " + res.status);
          }
          let filename = res.data.name;
          console.log(i + 1 + "\t" + fileId + "\t" + filename);
          resolve(filename);
        }
      );
    });
  }

  return res.status(200).json({
    message: "Renamed " + ctr + " Files Successfully !",
    status: 200
  });
};

1 Ответ

0 голосов
/ 19 июня 2019

Вы используете fs.readFile, который является асинхронным, как отмечено M1K1O в комментариях.

Если вы используете узел 10 или более, вы можете использовать fs.promises.readFile и await его результат, поэтому он будет ждать его возврата, прежде чем продолжить выполнение или вашу программу.

...