等待子功能执行后再返回

时间:2019-06-19 07:50:20

标签: javascript node.js google-drive-api es6-promise google-sheets-api

因此,我有此脚本可以重命名Google云端硬盘上的文件。 它从Google Spreadsheet读取两列,分别包含fileID和filename。 在Google云端硬盘上查找具有fileId的文件,并使用工作表中的文件名对其进行重命名。 一切正常。为了使其更容易使用并作为API中的路由提供,我将其导出。

问题在于,主module.exports.rename()函数具有正在执行的所有这些子函数。它不等待执行和重命名,仅返回响应。 由于计数器ctr最初为1,因此它仅返回消息“已成功重命名1个文件!”。

我尝试使用设置为false的布尔变量。然后在getSheetandBatchRename()中将其设置为true,并在return上方为主函数添加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 :(得分:0)

您正在使用BufferedWriter,它是异步的,正如M1K1O在评论中指出的那样。

如果您使用的节点为10或更多,则可以使用fs.readFilefs.promises.readFile的结果,因此它将等待返回结果再继续执行程序或程序。

相关问题