Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何访问';答复';回调函数中app.get的参数_Javascript_Node.js_Google Api - Fatal编程技术网

Javascript 如何访问';答复';回调函数中app.get的参数

Javascript 如何访问';答复';回调函数中app.get的参数,javascript,node.js,google-api,Javascript,Node.js,Google Api,我想通过googledriveapi向EJS文件传递一个文件列表(obj) i、 我想写作 app.get('/',function(req,res){ res.render('index',obj); } 问题是我通过几个回调函数获取js对象。 此函数称为 fs.readFile('client_secret.json',processClientSecrets ); 这反过来又要求 function processClientSecrets(err,content) { if (er

我想通过googledriveapi向EJS文件传递一个文件列表(
obj

i、 我想写作

app.get('/',function(req,res){
  res.render('index',obj);
}
问题是我通过几个回调函数获取js对象。 此函数称为

fs.readFile('client_secret.json',processClientSecrets );
这反过来又要求

function processClientSecrets(err,content) {
if (err) {
  console.log('Error loading client secret file: ' + err);
  return;
}else{
  authorize(JSON.parse(content),findFiles);
 }
}
这就叫这两个,

function authorise(credentials,callback) {
var clientSecret = credentials.installed.client_secret;
  var clientId = credentials.installed.client_id;
  var redirectUrl = credentials.installed.redirect_uris[0];
  var auth = new googleAuth();
  var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);

  // Check if we have previously stored a token.
  fs.readFile(TOKEN_PATH, function(err, token) {
    if (err) {
      getNewToken(oauth2Client, callback);
    } else {
      oauth2Client.credentials = JSON.parse(token);
      callback(oauth2Client);
    }
  });
}
[编辑]

function findFiles(auth){
var obj ={};
var key = 'files';
obj[key]=[];
var drive = google.drive('v3');
drive.files.list({
                auth: auth,
                folderId: '****************',
                q: "mimeType contains 'application/pdf' and trashed = false"
                },
  function(err,response){
    var f = response.files;
    if (f.length == 0) {
    console.log('No files found.');
    }else {
        var i;
        for (i = 0; i < f.length; i++) {
        var file = f[i];
        //console.log('%s (%s)', file.name, file.id);
        obj[key].push(file.name + ' ' + file.id);
        }
        console.log(obj);
        return obj;
  }
                  });

}
函数findFiles(auth){
var obj={};
var key='files';
obj[key]=[];
var-drive=google.drive('v3');
drive.files.list({
auth:auth,
folderId:“*******************”,
q:“mimeType包含'application/pdf'和trashed=false”
},
功能(错误、响应){
var f=response.files;
如果(f.length==0){
log('未找到任何文件');
}否则{
var i;
对于(i=0;i

这看起来是一个非常基本的问题,但是我无法解决它,因为node.js本质上是异步的,我所有返回obj的尝试都导致在检索obj之前呈现obj。

欢迎使用回调地狱。:-)旧的“节点”方式是进行嵌套回调,这会很快变得非常糟糕

现代方法是使用承诺,这使得将多个异步操作组合在一起变得更容易。让您自己的异步函数返回承诺,对于节点API函数(或尚未提供承诺的附加LIB),使用包装器使其启用承诺(手动或使用类似的方法)

例如,对于基于承诺的函数,您的调用将如下所示:

app.get('/',function(req,res){
    readFilePromise('client_secret.json')
        .then(content => JSON.parse(content))
        .then(authorise)
        .then(findFiles)
        .then(files => {
            res.render('index', files);
        })
        .catch(err => {
            // Render error here
        });
});
function authorise(credentials) {
    var clientSecret = credentials.installed.client_secret;
    var clientId = credentials.installed.client_id;
    var redirectUrl = credentials.installed.redirect_uris[0];
    var auth = new googleAuth();
    var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);

    // Check if we have previously stored a token.
    return readFilePromise(TOKEN_PATH)
        .then(token => {
            oauth2Client.credentials = JSON.parse(token);
            return oauth2Client;
        });
}
或者因为
JSON.parse
findFiles
都不是异步的:

app.get('/',function(req,res){
    readFilePromise('client_secret.json')
        .then(content => authorise(JSON.parse(content)))
        .then(auth => {
            res.render('index', findFiles(auth));
        })
        .catch(err => {
            // Render error here
        });
});
如果函数需要一个参数并返回处理后的结果,那么使用非异步函数
then
也可以,因此第一个版本也可以,尽管其中涉及一些开销

在这两种情况下,
readFilePromise
都是
readFile
的预期版本,并且
authorize
看起来像这样:

app.get('/',function(req,res){
    readFilePromise('client_secret.json')
        .then(content => JSON.parse(content))
        .then(authorise)
        .then(findFiles)
        .then(files => {
            res.render('index', files);
        })
        .catch(err => {
            // Render error here
        });
});
function authorise(credentials) {
    var clientSecret = credentials.installed.client_secret;
    var clientId = credentials.installed.client_id;
    var redirectUrl = credentials.installed.redirect_uris[0];
    var auth = new googleAuth();
    var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);

    // Check if we have previously stored a token.
    return readFilePromise(TOKEN_PATH)
        .then(token => {
            oauth2Client.credentials = JSON.parse(token);
            return oauth2Client;
        });
}
(还要注意-主观性警告!-因为我们最终不会得到地狱般的深度嵌套回调结构,所以我们可以使用合理的缩进宽度,而不是许多节点程序员认为需要采用的两个空格。)

进一步说,如果您使用的是Node V8.x+,则可以使用
async
/
wait
语法来使用这些承诺:

app.get('/', async function(req, res){
    try {
        const credentials = JSON.parse(await readFilePromise('client_secret.json'));
        const auth = await authorize(credentials);
        const files = findFiles(auth);
        res.render('index', files);
    } catch (e) {
        // Render error here
    }
});
请注意
async
before
function
wait
在调用返回承诺的函数时。
async
函数在封面下返回承诺,
wait
使用封面下的承诺。代码看起来是同步的,但不是。每个
wait
实际上都是对
的调用,然后在承诺完成时注册回调。类似地,
try
/
catch
实际上是对承诺链上的
catch
方法的调用

如果我们愿意,我们可以将其浓缩:

app.get('/', async function(req, res){
    try {
        res.render('index', findFiles(await authorize(JSON.parse(await readFilePromise('client_secret.json'))));
    } catch (e) {
        // Render error here
    }
});
…但可读性/可调试性受到影响。:-)

重要提示:将
async
函数传递到不希望函数返回承诺的对象(如
app.get
)时,必须将其包装在
try
/
catch
中,如上所述,并处理任何错误,因为如果调用代码不希望承诺,它将不会处理承诺拒绝,你需要这样做;未经处理的拒绝是一件坏事(在Node的未来版本中,将导致进程终止)

如果将
async
函数传递到中时,确实期望函数返回一个进程,那么最好不要使用
try/
捕捉器,允许错误传播


您请求有关
查找文件的帮助。我建议学习
promisify
或类似的东西。(在我看来)解决这个问题的正确方法是为自己提供一个理想版本的
drive.files.list
,因为
drive.files.list
使用节点式回调

但在没有承诺的情况下,我们可以这样做:

function findFiles(auth) {
    var drive = google.drive('v3');
    return new Promise(function(resolve, reject) {
        drive.files.list({
            auth: auth,
            folderId: '****************',
            q: "mimeType contains 'application/pdf' and trashed = false"
        },
        function(err, response) {
            if (err) {
                reject(err);
                return;
            }
            var f = response.files;
            if (f.length == 0) {
                console.log('No files found.');
            }
            else {
                var key = 'files'; // Why this indirection??
                resolve({[key]: f.map(file => file.name + ' ' + file.id)});
                // Without the indirection it would be:
                // resolve({files: f.map(file => file.name + ' ' + file.id)});
            }
        });
    });
}
如果我们有一个明确的版本,并且取消了似乎不必要的
间接寻址,那么它会更简单:

function findFiles(auth) {
    return drivePromisified.files.list({
        auth: auth,
        folderId: '****************',
        q: "mimeType contains 'application/pdf' and trashed = false"
    }).then(files => ({files: files.map(file => file.name + ' ' + file.id)}));
}
或者作为使用
wait
async
函数:

async function findFiles(auth) {
    const files = await drivePromisified.files.list({
        auth: auth,
        folderId: '****************',
        q: "mimeType contains 'application/pdf' and trashed = false"
    });
    return {files: files.map(file => file.name + ' ' + file.id)};
}

先生,谢谢您的回答,实际上我的
findFile
函数也是异步的,您能帮我保证一下吗,@AlwaysUngrie:很棘手,因为您没有显示它的内容。:-)但对读者来说,这是最好的练习:让它回报一个承诺。例如,如果使用,您可以像上面的
readFile
那样承诺,并从中返回承诺(如果您需要转换结果,可以使用
然后将其链接到
)。很抱歉,我将问题编辑为包含
findFile
,我尝试返回drive.files.list,但代码只进入catch(e)块。@AlwaysUngrie:我建议您花些时间学习promisify教程,了解promisify或类似内容。当你不必学习旧的回调地狱方式时,你就可以跳转到更干净的
async
/
wait
(或者至少是承诺)领域。我在答案的末尾加了一句。快乐编码!你给我的解决方案澄清了我对承诺的所有概念:)。希望现在我能够在没有错误的情况下编写异步代码。如果控件到达readFile,然后转到Authorization(我可以记录Authorization返回的对象),我无法感谢您,但在这之后它会捕获错误:(