Async Await无法与Google drive API配合使用。

问题描述 投票:0回答:1

我是JavaScript和AsyncAwait概念的新手。

我正在使用驱动API 例子 并能够打印出我的驱动器中的文件。但当我尝试将响应存储到一个名为 files 控制台正在打印未定义。

我认为 console.log(files) 是在生成响应之前打印的?

有什么办法可以让 listFiles() 函数等待文件变量充满响应,这样我就可以将数据发送到我的前端?


'use strict'

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.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 TOKEN_PATH = 'token.json';

// Load client secrets from a local file.


class FileUploadController {

    index ({ request, response, view }) {
        fs.readFile('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), listFiles);
        });

        /**
         * 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);
                });
            });
        }

        let files;
        /**
         * Lists the names and IDs of up to 10 files.
         * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
         */
        async function listFiles(auth) {
            const drive = google.drive({version: 'v3', auth});
            // await drive.files.list({
            //     pageSize: 10,
            //     fields: 'nextPageToken, files(id, name)',
            // }, (err, res) => {
            //     if (err) return console.log('The API returned an error: ' + err);                
            //     files = res.data.files;
            //     console.log(files)
            //     if (files.length) {
            //     console.log('Files:');
            //     files.map((file) => {
            //         console.log(`${file.name} (${file.id})`);
            //     });
            //     } else {
            //     console.log('No files found.');
            //     }
            // });
            drive.files.list({
                pageSize: 10,
                fields: 'nextPageToken, files(id, name)',
            }).then( res => {
                files = res.data.files
                console.log(files);
            })
        }

        console.log(files);



    return view.render('file-upload', {files: 'files are here'})

    }


}

module.exports = FileUploadController


当这个控制器运行时,我的终端显示了以下内容

info: serving app on http://127.0.0.1:3333
undefined
[ { id: '1Pg5KODwcdlG7oV64pOSl9tBMtzy_p498', name: 'photo.jpg' },
  { id: '1_u248zVI2swg0KLMaL9oRERkGUNHbV2u', name: 'photo.jpg' },
  { id: '1duLnJrPYkd75ZNFZx0OvTUPYYmZAaNzS', name: 'photo.jpg' },
  { id: '1TJC6-VfuusA6rXgtC9E3WQQsFg4JZJkn',
    name: 'etosEntityDiagram.drawio' },
  { id: '1XUg_Xju4hZr2KTEsEt8WHz0bAz8isAEo',
    name: 'Untitled Diagram.drawio' },
  { id: '14MsZFOZGLZqEZyNbI0yYTo4I4aW0gK7K',
    name: 'ProjectFileManager.drawio' },
  { id: '0B3g4WnyGCaYQdExQSm9ZYmkwRTQ',
    name: 'High Elves - 8th Edition.pdf' },
  { id: '1ok4WdMaalXWd9y0PGENewMlElPUxEqTNY3p8wwch_h4',
    name: 'Google VM Pricing' },
  { id: '1GhRSL8y9jzm8eefwFFvCp2AuJhtGUOEx', name: 'gcp.drawio' },
  { id: '1OC_D8CNe7CXzzkJpMNYKkVT1KteS2vQulov2E-D5KNs',
    name: 'Bucket Pricing Example' } ]


javascript node.js async-await google-api es6-promise
1个回答
1
投票

对不起,我不太明白你到底想做什么,用 async/await 或者只是了解如何转移 files 丝毫不影响 render 方法。我把你的代码在 async/await由于你没有提供服务器,我无法检查。我希望它能让你更清楚地了解如何使用 async/await:

'use strict'

const fs = require('fs');
const util = require('util');
const readline = require('readline');
const { google } = require('googleapis');

const fsp = fs.promises;

readline.Interface.prototype.question[util.promisify.custom] = function(prompt) {
    return new Promise(resolve =>
        readline.Interface.prototype.question.call(this, prompt, resolve),
    );
};

readline.Interface.prototype.questionAsync = util.promisify(readline.Interface.prototype.question);

// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/drive.metadata.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 TOKEN_PATH = 'token.json';

class FileUploadController {

    async index({ request, response, view }) {
        try {
            const files = await this.getFiles();
            return view.render('file-upload', { files });
        } catch (error) {
            // ... you must handle the error
        }
    }

    async getFiles() {
        try {
            // Load client secrets from a local file.
            const content = await fsp.readFile('credentials.json');
            const oAuth2Client = await this.authorize(JSON.parse(content));
            const files = await this.listFiles(oAuth2Client);
            return files;
        } catch (error) {
            console.error('Error loading client secret file:', error);
            throw error;
        }
    }

    /**
     * Create an OAuth2 client with the given credentials, and then execute the
     * given callback function.
     * @param {Object} credentials The authorization client credentials.
     */
    async authorize(credentials) {
        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.
        try {
            const token = await fsp.readFile(TOKEN_PATH);
            oAuth2Client.setCredentials(JSON.parse(token));
            return oAuth2Client;
        } catch (error) {
            console.error(error);
            return this.getAccessToken(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.
     */
    async getAccessToken(oAuth2Client) {
        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,
        });

        const code = await rl.questionAsync('Enter the code from that page here: ');
        rl.close();

        try {
            const token = await oAuth2Client.getToken(code);
            oAuth2Client.setCredentials(token);
            // Store the token to disk for later program executions
            await fsp.writeFile(TOKEN_PATH, JSON.stringify(token));
            return oAuth2Client
        } catch (error) {
            console.error('Error retrieving access token', error);
            throw error;
        }
    }

    /**
     * Lists the names and IDs of up to 10 files.
     * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
     */
    async listFiles(auth) {
        try {
            const drive = google.drive({ version: 'v3', auth });
            const response = await drive.files.list({
                pageSize: 10,
                fields: 'nextPageToken, files(id, name)',
            });
            return response.data.files;
        } catch (error) {
            console.error('The API returned an error:', error);
            throw error;
        }
    }

}

module.exports = FileUploadController;

我并不是说这段代码写得百分之百好,但它确切地展示了如何使用这些代码。async/await 以及如何获得 files 变量,以便将其传递给渲染。

© www.soinside.com 2019 - 2024. All rights reserved.