Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.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 Node.JS和Express res.redirect()未启用新网页_Javascript_Node.js_Express - Fatal编程技术网

Javascript Node.JS和Express res.redirect()未启用新网页

Javascript Node.JS和Express res.redirect()未启用新网页,javascript,node.js,express,Javascript,Node.js,Express,我正在尝试将变量保存到文本文件,但如果在使用spotifyApi.clientCredentialsGrant时找不到该变量,则我希望服务器重定向到app.get'/error',functionreq,res{};显示不同的网页,但返回错误: 节点:11484 UnhandledPromiseRejectionWarning:错误[ERR_HTTP_HEADERS_SENT]:发送到客户端后无法设置头 如何绕过此错误以显示网页error.html 我没有访问EJS或window.locatio

我正在尝试将变量保存到文本文件,但如果在使用spotifyApi.clientCredentialsGrant时找不到该变量,则我希望服务器重定向到app.get'/error',functionreq,res{};显示不同的网页,但返回错误:

节点:11484 UnhandledPromiseRejectionWarning:错误[ERR_HTTP_HEADERS_SENT]:发送到客户端后无法设置头

如何绕过此错误以显示网页error.html

我没有访问EJS或window.location的权限,因为它分别与其他文件冲突,并且是一个node.js程序

app.get('/', function (req, res) {
    res.sendFile(path.join(__dirname, '/public', 'homepage.html'));
        try {
            spotifyApi.clientCredentialsGrant()
                .then(function (data) {
                    // Save the access token so that it's used in future calls
                    client_cred_access_token = data.body['access_token'];
                    console.log(client_cred_access_token);
                    console.log('Client Credentials Success!');
                }, function (err) {
                    console.log('Something went wrong when retrieving an access token', err.message);
                    throw err;

                });
            fs.writeFile("./public/client_cred_token.txt", '', function (err) {
                console.log('Clearing previous access token');
            });
            fs.writeFile("./public/client_cred_token.txt", client_cred_access_token, function (err) {
                if (err) return console.log(err);
            });
            fs.readFile('./public/client_cred_token.txt', function (err, data) {
                if (err) throw err;
                console.log("Saved Client Credentials as: %s", data)
            });
        }
        catch (err) {
            res.redirect('/error');
        }
});
接受答案的关键是,在确认需要哪个HTML/文件之前,不要向服务器发送任何HTML/文件。

应用程序获取“/”,函数请求,res{ 试一试{ spotifyApi.clientCredentialsGrant.Then函数数据{ //保存访问令牌,以便在将来的调用中使用 让客户端访问令牌=data.body['access\u token'; console.logclient_cred_access_令牌; console.log“客户端凭据成功!”; //截断令牌文件 fs.truncateSync./public/client_cred_token.txt; //将令牌写入文件 fs.writeFileSync./public/client\u cred\u token.txt,client\u cred\u access\u token; //再次从文件中读取令牌 //注意:您可以在此处使用'client\u cred\u access\u token' 让data=fs.readFileSync'/public/client_cred_token.txt'; console.Log已将客户端凭据保存为:%s,数据 //在未引发错误时向客户端发送主页 res.sendFilepath.join_uudirname,“/public”,“homepage.html”; },函数错误{ 日志“检索访问令牌时出错”,err.message; 犯错误; }; }犯错误{ res.redirect'/错误'; } }; 您首先调用res.sendFile,然后如果稍后出现错误,您还将调用res.redirect'/error',这意味着您将尝试向一个触发您看到的错误的http请求发送两个响应。你不能那样做

解决方案是在所有其他操作结束时调用res.sendFile,以便在成功时调用它,在出现错误时调用res.redirect,从而只调用其中一个

与这里的另一个答案不同的是,我已经向您展示了如何使用异步文件I/O正确地编写代码,这样设计就可以在真正的服务器中使用,该服务器可以满足多个用户的需求

const fsp = require('fs').promises;

app.get('/', async function (req, res) {
    try {
        let data = await spotifyApi.clientCredentialsGrant();
        // Save the access token so that it's used in future calls
        client_cred_access_token = data.body['access_token'];
        console.log(client_cred_access_token);
        console.log('Client Credentials Success!');
        await fsp.writeFile("./public/client_cred_token.txt", client_cred_access_token);
        let writtenData = await fsp.readFile('./public/client_cred_token.txt');
        console.log("Saved Client Credentials as: %s", writtenData);
        res.sendFile(path.join(__dirname, '/public', 'homepage.html'));
    } catch (err) {
        console.log(err);
        res.redirect('/error');
    }
});

您首先发送html文件,因此所有的头都被发送,您必须在try块的末尾移动它们。永远不要在服务器的请求处理程序中使用fs函数的同步版本。它会破坏服务器的可伸缩性,因为它会在每次同步fs操作期间阻塞整个事件循环。还有,犯错误;在你拥有它的地方,它将毫无用处。由于您所处的异步回调,try/catch不会捕获它。@jfriend00抛出错误;很好,因为从promise-catch函数可以传递错误。假设在令牌存储逻辑上,OP似乎有超过1个用户它用于学校项目,而不是后勤服务器使用,所以这是正确的。我仍然有一些错误,我可以通过更改catch err来修复,改为只发送error.html,这总体上更干净。马克,非常好,简洁,明智的回答。谢谢:@RhettJarvis-如果我在给基于服务器的学校作业评分,我会因为在请求处理程序中使用同步文件I/O而对其进行评分。这不是任何人应该如何学习编写请求处理程序。