• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Wyświetlenie danych z pliku json na stronie w aplikacji NODE.JS

0 głosów
73 wizyt
pytanie zadane 8 kwietnia w JavaScript przez rszczepanski02 Użytkownik (690 p.)

Dzień dobry. Mam pewien mały problem. Obecnie uczę się node.js i express'a i chciałem sobie poćwiczyć tworząc prosty projekt wysyłania i wyświetlania komentarzy na stronie internetowej. Komentarze umieszczane są w pliku json i wysyłane za pomocą prostego formularza w pug. Wysyłanie działa, jednak mam problem z wyświetleniem komentarzy. Wiem, że moduł fs jest asynchroniczny i z tego też względu mam duży problem, gdyż przekazanie danych z CommentController.js do index.js powoduje zwrot wartości w postaci undefined. Liczę na pomoc :)

index.js

const express = require('express');
const router = express.Router();
const CommentController = require('../controllers/CommentController');

/* GET home page. */
router.get('/', function(req, res, next) {

  CommentController.getObject;

  res.render('index', { title: 'Komentarze'});
});

router.post('/', CommentController.store)

module.exports = router;

 

CommentController.js

const fs = require('fs');

function getObject(data) {
    return data;
}


module.exports = {
    store: (req, res) => {

        let name = req.body.name;
        let comment = req.body.comment;
    
        if(name == '' || comment == '') {
            res.render('index', {title: 'Komentarze', error: 'Musisz wypełnić formularz'});
        } else {
    
            fs.readFile('data.json', 'utf-8', (err, data) => {
                if(err) return res.render('index', {title: 'Komentarze', error: 'Nie udało się wysłać komentarza'});
                else {
                    let arrayObjects = JSON.parse(data);
                    arrayObjects.comments.push({
                        "name": name,
                        "comment": comment
                    });
    
                    fs.writeFile('data.json', JSON.stringify(arrayObjects), 'utf-8', (err) => {
                        if(err) return res.render('index', {title: 'Komentarze', error: 'Musisz wypełnić formularz'});
                        else {
                            res.render('index', {title: 'Komentarze', success: 'Komentarz został wysłany!'}); 
                        }
                    });
                }
            });
        }  
    },

    object: () => {
        fs.readFile('data.json', 'utf-8', (err, data) => {
            if(err) return res.render('index', {title: 'Komentarze', error: 'Nie można wyświetlić listy komentarzy!'});
            else {
                let jsonData = JSON.parse(data);
                let objectList = jsonData.comments;
                return objectList;
            }
        });
    }
};

 

index.pug

extends layout

block content
  header
    .container
      h1= title
      p Wypełnij formularz, aby dodać komentarz
  
  .container
    form(action="/" method="POST")
      input(type="text" name="name" placeholder="Wpisz swoją nazwę")
      textarea(type="text" name="comment" placeholder="Treść komentarza")
      button(id="comment-submit" class="btn-primary") Wyślij
    
    .alert-box
      p(class="error-alert")= error
      p(class="success-alert")= success

    .comments-object
      .comment-name
        p
      .comment-body
        p

 

app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

 

Pozdrawiam :)

2 odpowiedzi

0 głosów
odpowiedź 8 kwietnia przez ScriptyChris Mędrzec (168,660 p.)

Wiem, że moduł fs jest asynchroniczny

Jeśli operacja wczytywania pliku nie będzie odczuwalnie spowalniać wątku, to możesz skorzystać z synchronicznego odpowiednika.

Co do problemu, to użycie return w callbacku przekazanym do asynchronicznej funkcji nie będzie działać, bo nie da się zwrócić wartości z kodu asynchronicznego. Możesz przekazać wartość wyjściową do callbacka, albo zwrócić całość w postaci promisa - po stronie Node możesz skorzystać z utila do wrapowania funkcji w promisy.

Z tego co widze, to moduł CommentController ma prywatną funkcję getObject, ale udostępnia metodę object - więc nie wiem co ma na celu użycie CommentController.getObject w module index.js?

komentarz 8 kwietnia przez rszczepanski02 Użytkownik (690 p.)
Mógłbyś proszę podać jakiś przykład w kodzie? Ciężko mi się odnieść w dokumentacji node. Jeszcze jestem w tym zbyt lewy.

Co do ostatniego akapitu to wiem. Po prostu trochę kombinowałem i zostało to po starym kodzie.
1
komentarz 8 kwietnia przez rszczepanski02 Użytkownik (690 p.)
W sposób synchroniczny się udało jednak chciałbym również wiedzieć jak to zrobić przy użyciu asynchronicznym.
komentarz 8 kwietnia przez ScriptyChris Mędrzec (168,660 p.)

Niech funkcja zwraca promisa (możesz zawczasu owinąć fs.readFile we wspomniany utils.promisify):

    object: () => {
        return new Promise((resolve, reject) => { // zwrócenie promisa
          fs.readFile('data.json', 'utf-8', (err, data) => {
              if(err) {
                 res.render('index', {title: 'Komentarze', error: 'Nie można wyświetlić listy komentarzy!'});
                 reject(err); // odrzucenie promisa
              }
              else {
                  let jsonData = JSON.parse(data);
                  let objectList = jsonData.comments;

                  resolve(objectList); // rozwiązanie promisa
              }
          });
        })
    }

i wywołanie:

CommentController.object()
  .then(
     value => console.log('value:', value), 
     error => console.error('error:', error)
   );

 

0 głosów
odpowiedź 8 kwietnia przez rszczepanski02 Użytkownik (690 p.)

Udało mi się rozwiązać ten problem, jednak pojawił się inny i tym razem nie mam pojęcia skąd się może brać.

D:\web dev\kurs node.js\express-comments\views\index.pug:21 19| 20| .grid-box > 21| each test in data 22| .comments-object 23| .comment-name 24| p= test.name Cannot read property 'length' of undefined

 

W momencie wysyłania nowego komentarza na serwer pętla umieszczona w pug nie może odczytać właściwości length. Nie mam pomysłu heh.

 

CommentController.js

const fs = require('fs');

module.exports = {
    store: (req, res) => {

        let name = req.body.name;
        let comment = req.body.comment;
    
        if(name == '' || comment == '') {
            res.render('index', {title: 'Komentarze', error: 'Musisz wypełnić formularz'});
        } else {
    
            fs.readFile('data.json', 'utf-8', (err, data) => {
                if(err) return res.render('index', {title: 'Komentarze', error: 'Nie udało się wysłać komentarza'});
                else {
                    let arrayObjects = JSON.parse(data);
                    arrayObjects.comments.push({
                        "name": name,
                        "comment": comment
                    });
    
                    fs.writeFile('data.json', JSON.stringify(arrayObjects), 'utf-8', (err) => {
                        if(err) return res.render('index', {title: 'Komentarze', error: 'Musisz wypełnić formularz'});
                        else {
                            res.render('index', {title: 'Komentarze', success: 'Komentarz został wysłany!'}); 
                        }
                    });
                }
            });
        }  
    },

    object: (req, res) => {

        fs.readFile('data.json', (err, data) => {
            let obj = JSON.parse(data);
            if (err) res.send(err);
            res.render('index', {
                title: 'Komentarze',
                data: obj.comments
            });
        });

    }
};

 

index.js

const express = require('express');
const router = express.Router();
const CommentController = require('../controllers/CommentController');

/* GET home page. */
router.get('/', CommentController.object);

router.post('/', CommentController.store)

module.exports = router;

 

index.pug

extends layout

block content
  header
    .container
      h1= title
      p Wypełnij formularz, aby dodać komentarz
  
  .container
    .left-side
      form(action="/" method="POST")
        input(type="text" name="name" placeholder="Wpisz swoją nazwę")
        textarea(type="text" name="comment" placeholder="Treść komentarza")
        button(id="comment-submit" class="btn-primary") Wyślij
      
      .alert-box
        p(class="error-alert")= error
        p(class="success-alert")= success

    .grid-box
      each test in data
        .comments-object
            .comment-name
              p= test.name
            .comment-body
              p= test.comment

 

Podobne pytania

0 głosów
1 odpowiedź 194 wizyt
0 głosów
1 odpowiedź 986 wizyt
pytanie zadane 8 kwietnia 2018 w JavaScript przez jegor377 Stary wyjadacz (13,230 p.)
0 głosów
0 odpowiedzi 80 wizyt

85,871 zapytań

134,644 odpowiedzi

298,914 komentarzy

56,738 pasjonatów

Advent of Code 2021

Top 15 użytkowników

  1. 926p. - rucin93
  2. 925p. - Whistleroosh
  3. 912p. - nidomika
  4. 876p. - adrian17
  5. 867p. - Michal Drewniak
  6. 866p. - Mikbac
  7. 863p. - Mateusz Bogdan
  8. 859p. - CC PL
  9. 797p. - Argeento
  10. 704p. - ScriptyChris
  11. 683p. - tokox
  12. 660p. - Vinox
  13. 645p. - TheLukaszNs
  14. 642p. - s. Dorota Kowalewska
  15. 601p. - Marcin Harasimowicz
Szczegóły i pełne wyniki

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...