Node.JS и Express res.redirect () не включают новую веб-страницу - PullRequest
0 голосов
/ 26 февраля 2020

Я пытаюсь сохранить переменную в текстовом файле, но если переменная не найдена при использовании spotifyApi.clientCredentialsGrant(), я хочу, чтобы мой сервер перенаправил на app.get('/error', function(req, res) {});, который отображает другую веб-страницу, но возвращает ошибка:

(узел: 11484) UnhandledPromiseRejectionWarning: Ошибка [ERR_HTTP_HEADERS_SENT]: невозможно установить заголовки после их отправки клиенту

Как можно обойти эту ошибку для отображения ошибки веб-страницы. html?

У меня нет доступа к E JS или 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 / файлы на сервер, пока не будет подтверждено, какой из них необходим.

Ответы [ 2 ]

1 голос
/ 26 февраля 2020

Сначала вы звоните res.sendFile(), а затем, если позже вы получите сообщение об ошибке, вы также звоните res.redirect('/error'), что означает, что вы попытаетесь отправить два ответа на один запрос http, который вызовет ошибку, которую вы видите. Вы не можете этого сделать.

Решение состоит в том, чтобы вызывать res.sendFile() в конце всех ваших других операций, чтобы вы могли затем вызывать его в случае успеха и вызывать res.redirect() в случае ошибки и, таким образом, вызывать только один или другой.

В отличие от другого ответа здесь, я показал вам, как правильно кодировать это с помощью асинхронного файлового ввода-вывода, чтобы проект мог использоваться на реальном сервере, предназначенном для обслуживания потребности более чем одного пользователя.

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');
    }
});
0 голосов
/ 26 февраля 2020

app.get('/', function (req, res) {
    try {

        spotifyApi.clientCredentialsGrant().then(function (data) {

            // Save the access token so that it's used in future calls
            let client_cred_access_token = data.body['access_token'];
            console.log(client_cred_access_token);
            console.log('Client Credentials Success!');

            // truncate token file
            fs.truncateSync("./public/client_cred_token.txt");

            // write token to file
            fs.writeFileSync("./public/client_cred_token.txt", client_cred_access_token);

            // read token from file again
            // NOTE: you could use `client_cred_access_token` here
            let data = fs.readFileSync('./public/client_cred_token.txt');
            console.log("Saved Client Credentials as: %s", data)

            // send homepage to client when no error is thrown
            res.sendFile(path.join(__dirname, '/public', 'homepage.html'));

        }, function (err) {
            console.log('Something went wrong when retrieving an access token', err.message);
            throw err;

        });

    } catch (err) {
        res.redirect('/error');
    }
});

Я поменял все операции с асинхронными файлами на синхронизирующую. Они выдают ошибку, и вам не нужно иметь дело с цепочкой / потоком обратного вызова.

Также я переместил sendFile(...) в нижнюю часть блока try, поэтому при возникновении ошибки из любого вызова функции syncrhonus sendFile не достигается, и ваше перенаправление может быть отправлено клиенту.

В противном случае вы бы отправили homepage.html клиенту со всеми заголовками, и перенаправление невозможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...