EJS не отображается

Я делаю игру «Камень, ножницы, бумага» на серверной части Node.js с экспресс-сервером, клиентской частью frontend.js, файлами index.ejs и main.css. Сначала я хочу отобразить строковую строку результата вашего решения (выиграл, проиграл, то же самое — попробуйте еще раз). Однако это не дает результата. Я попытался использовать console.info, чтобы определить, передаются ли данные между маршрутами, что действительно происходит и буквально показывает, что данные находятся в шаблоне ejs, но они все равно не отображаются. Я пытался использовать чат GPT, чтобы разобраться в этом, но безуспешно...

бэкэнд.js:

    import express from "express";
import bodyParser from "body-parser";
import pg from "pg";
import ejs from "ejs";
import axios from "axios";
import { dirname } from "path";
import { fileURLToPath } from "url";


// import icons from "bootstrap-icons";
const __dirname = dirname(fileURLToPath(import.meta.url));
const app = express();
const port = 3000;


let gameResult = [];

app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));


app.get("/", (req, res) => {

   const results = [...gameResult];
    gameResult = [];

    console.info("Result from session:", results);

    res.render("index", {results});
});

app.post("/add", (req,res) => {

    const {targetedId, dataIdList} = req.body;

    let compSelector = dataIdList[Math.floor(Math.random() * dataIdList.length)];

    console.info(`Chosen by client: ${targetedId}`);
    console.info(`Chosen by computer: ${compSelector}`);



  function determineResult(targetedId, compSelector) {

    switch (targetedId) {
        case "paper":
            if (compSelector === "scissors") {
                return "You lost";
                
            } else if (compSelector === "rock") {
                return "You won!";
                
            } else {
                return "The same, try again";
                
            }
            break;

        case "scissors":
            if (compSelector === "rock") {
                return "You lost";

            } else if (compSelector === "paper") {
                return "You won!"

            } else {
                return "The same, try again";
            }
            break;

            case "rock":
                if (compSelector === "paper") {
                    return "You lost";
    
                } else if (compSelector === "scissors") {
                    return "You won!"
    
                } else {
                    return "The same, try again";
                }
            break;

        default:
            console.info("Error");
            break;
    }

 }

 try {
    const result = determineResult(targetedId, compSelector);
    console.info(result);
   
    gameResult = [result];
   
    res.redirect("/");
 } catch (error) {
    console.error("Error handling POST /add request:", error);
        res.status(500).send("Internal Server Error");
 }




});



app.listen(port, () => {
    console.info(`Listening on port ${port}`);
});

интерфейс.js:

console.info("Frontend.js is loaded");

function myFrontFunction(event) {

    const selectedImage = event.target;
    const targetedId = selectedImage.getAttribute("data-id");
    const images = document.querySelectorAll(".image");
    const dataIdList = [];

    images.forEach(dataId => {
       dataIdList.push(dataId.getAttribute("data-id"));
    });

    console.info(`Data list: ${dataIdList}`);


// console.info(typeof(idData));


    console.info(targetedId);

    fetch("/add", {
        method: "POST",
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify({targetedId, dataIdList}),
    })
    .then(response => {

        if (response.ok) {
        console.info("Data sent successfully");
        response.text().then(text => console.info(text));
        console.info("All images:", images); 

        images.forEach(image => {
            if (image !== selectedImage){
                console.info("Hiding image:", image);
                image.classList.add('hidden'); // Use class to hide
            }
        });
        } else {
            console.error("Failed to send data to the server");
        }

        

    })
    .catch(error => console.error("Error:", error));

}

индекс.ejs:

<%- include('partials/header.ejs') %>


<h1>The RSP App!</h1>

<h2>Choose Rock, Scissors or Paper:</h2>

<img class = "image" src = "/images/paper.png" alt = "A piece of paper" width = "400px" height = "400px" data-id = "paper" onclick = "myFrontFunction(event)">
<img class = "image" src = "/images/rock.png" alt = "A rock" width = "400px" height = "400px" data-id = "rock" onclick = "myFrontFunction(event)">
<img class = "image" src = "/images/scissors.png" alt = "Scissors" width = "400px" height = "400px" data-id = "scissors" onclick = "myFrontFunction(event)">


<div>
<% if (results.length > 0) { %>
    <% results.forEach( result => { %>
       <p> <%= result %></p>
    <% }) %>
<% } %>
</div>






<script src = "/frontend.js"></script>

<%- include('partials/footer.ejs') %>

основной.css:

.hidden {
    display: none;
}

Действительно, почему это сложно? Это просто (довольно простая) игра

KooiInc 26.07.2024 18:52

Привет! Для меня это отображается, я не пробовал включать оператор <script src = "/frontend.js"></script>.

WeDoTheBest4You 27.07.2024 09:47
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Из-за того, как вы настроили свой код, он не может отображать результаты. Давайте разберемся, что происходит:

  1. Пользователь открывает страницу / и может выбрать одно из изображений.
  2. После щелчка по любому изображению, скажем, ножницам, вы отправляете запрос POST на /add на серверную часть с данными {targetedId: "scissors", dataIdList: ["paper", "rock", "scissors"]}
  3. Обработчик маршрута /add выбирает случайный вариант, а затем проверяет результат.
  4. Как только результат определен, массив gameResults теперь будет содержать результат и отвечать перенаправлением на /. Обработчик маршрутизатора для этого маршрута затем примет и сбросит значение gameResults, так что теперь gameResults снова станет пустым массивом.
  5. Страница будет обработана, и визуализированная разметка будет отправлена ​​обратно на запрос выборки в качестве ответа. Это означает, что строка response.text().then(text => console.info(text)); должна печатать HTML-разметку для всей страницы с отображаемыми результатами. Но поскольку со страницей, на которой находится пользователь, ничего не делается, ничего, кроме «скрытия» ненажатых изображений и консольного журнала разметки, не произойдет.
  6. Если пользователь попытается перезагрузить страницу, в результате он все равно ничего не покажет, потому что, если мы помним, перенаправление на / в обработчике /add сбросило значение gameResults на [].

Таким образом, по сути, вы в конечном итоге «игнорируете» результат, полученный с запросом на выборку, и в то же время отбрасываете значение на серверной стороне.

Итак, чтобы заставить ваш текущий код работать, вы можете отправить сам результат обратно в качестве ответа и добавить его на страницу в новом элементе, что-то вроде:

бэкэнд.js

 try {
    const result = determineResult(targetedId, compSelector);
   
    res.send(result);
 } catch (error) {
    ...
 }

интерфейс.js

fetch(...)
.then(res => res.text())
.then(text => {
  let p = document.createElement('p');
  p.textContent = text;
  document.querySelector('div').appendChild(p);
});

И есть много других способов сделать это, это зависит от того, как вы хотите это сделать. Если вы посмотрите на то, что @KooiInc ссылается в комментариях, вы увидите подход, который полностью работает на стороне клиента. Для новичка это может показаться немного пугающим, я рекомендую разделить строки несколькими символами новой строки, чтобы иметь лучший обзор и затем понять, что происходит.

Даже если вы хотите сделать это с помощью серверных вычислений и EJS, есть разные способы подойти к этому, но, как я уже сказал, в конечном итоге все сводится к тому, как вы хотите это сделать. Если вы хотите увидеть другой подход с бэкэндом+EJS, просто дайте мне знать :)

Другие вопросы по теме