NodeJS ve Ajax ile databaseden gerçek zamanlı veri çekmek

Merhabalar,
Basit bir Chat uygulaması yazmaya çalışıyorum. Socket.io kullanmadan AJAX’ı çözmeye çalışıyorum.
1-Textarea’daki veriyi submit ettiğimde serverda veriyi yakalıyorum
2- Veriyi DB’ye kaydediyorum
3- DB’den son veriyi çekip txt dosyasına yazıyorum.
4- onreadystatechange ile txt dosyasında değişiklik olduğunda tetiklenen fonksiyon ile innerHTML ile

elemanına txt içeriğini aktarıyorum. (Aslında bu şekilde işlediğinden de emin değilim ama amacım bu)
Durum şu ki forma yazı yazıp gönder dediğimde her şey tıkır tıkır işliyor ancak klasöre gidip txt dosyasını kendim değiştirdiğimde bu ekranıma yansımıyor. Sayfayı yenilemem gerekiyor.
İstediğim gerçek zamanlı olarak DataBase’den veri çekmek.
Sayfayı yenilemeksizin değişen veriyi ekranıma yansıtmak bu kadar zor olmamalı.

app.js

const express = require('express');

const app = express();

const path = require('path');

const mngs = require('mongoose');

const bodyparser = require('body-parser');

const fs = require('fs');

app.use('/public', express.static(path.join(__dirname, 'public'))); //express.static herkese açık klasörü belirler

app.use(bodyparser.urlencoded({extended:false})); // URL olarak gelen requestleri parçalayarak kullanımını kolaylaştırır

app.use(bodyparser.json({extended:false})); // JSON olarak gelen requestleri parçalayarak kullanımını kolaylaştırır

//mongo ile bağlantı kuruluyor "mongodb://127.0.0.1:27017" ifadesi standarttır. "/chatDB" ise oluşturduğumuz DB ismi

mngs.connect('mongodb://127.0.0.1:27017/chatDB',{ useNewUrlParser: true, useUnifiedTopology: true }, function(err,data){

  if (err){

      console.log('sunucu bağlantı hatası:'+err)

  }else{

  console.log('DB bağlandı...')}

});

//mongoose ile veri göndermek için önce veri tabanı şeması oluşturuyoruz, böylece giden veriler şema ile aynı yapıda DB'ye kaydolacak. "mesajlar" colection ismimizi gösterir

const Schema = mngs.Schema;

let DBsema = new Schema(

  {

  mesaj:String,

  tarih:{type:Date, default:Date.now}

  },

  {

    collection:'mesajlar'

  }

);

let ChatSema = mngs.model('ChatSema', DBsema);

//ana sayfa için index.html sayfasını gönderiyoruz

//Get metodu ile

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

    res.sendFile(__dirname + '/index.html');

});

//POST metodu ile

app.post('/', function (req, res) {

    res.sendFile(__dirname + '/index.html');

    console.log('post geldi');

    var varmesaj= req.body.mesaj;  

    ChatSema.create({ mesaj:varmesaj }, (err, result) => {

      if (err) throw err;

      console.log(result);

      veriyicek();

    });

});

  //mongoDB'den bütün collectionu çekip son gönderinin mesaj elemanını yakalıyoruz.

 function veriyicek(){

    ChatSema.find({},function(err,data){

    if (err) throw err;

    const DBlemansayisi=data.length;

    const yenidata=DBlemansayisi-1;

    var sonmesajelemani = data[yenidata].mesaj;

    console.log('  SON    Mesaj elemanı:'+sonmesajelemani);

    //DB'den yakaladığımız son elemanı txt dosyasına yazdırıyoruz

    fs.appendFile('./public/deneme.txt', '<br>'+sonmesajelemani+'<br>', function (err, data) {

      if (err) throw err;

      console.log('Veri başarıyla yazıldı.');

    });

  });

 };

//sunucu çalışmaya başlar

app.listen(9999, function () {

  console.log('Sunucu çalışıyor...');

});

index.html

<!DOCTYPE html>

<html>

<head>

<title>Page Title</title>

</head>

<body>

<FORM ACTION="/" METHOD=POST >

    <textarea TYPE=text NAME="mesaj"></textarea><br>

    <INPUT TYPE=submit  value="Mesajı Gönder">

</FORM>

<h1>Gelen mesajlarh1</h1>

<P>Gelen Mesajlar</P>

<script>

      var xhr = new XMLHttpRequest();

      var metinsec = document.querySelector('p');

      //document.querySelector('h1').innerHTML='deneme';

     

      xhr.onreadystatechange = function () {

        if (this.readyState == 4 && this.status == 200 || this.status == 304) {

            var xmldosyasi= xhr.responseText;

            metinsec.innerHTML=xmldosyasi;

            console.log(xmldosyasi);

        };

      };

   

      xhr.open('GET', 'public/deneme.txt', true);

      xhr.send();

    </script>

</body>

</html>
1 Beğeni

ile server a istek atıp cevap alıyorsun sürekli bir bağlantı kurmuyorsun, işte bu yüzden socket kullanılıyor.

Socket te bağlantı kurarsın ve o bağlantıyı sürekli dinlersin, bir cevap algıladığında socketin ilgili metodu çalışır.

Sen şunu yapabilrisin orka planda sürekli belli periyotlarda istek atıp kontrol etmen gerekir, bu da biraz maliyetli, o yüzden socket kullanılıyor, çünkü sockette bağlantıyı bir kere kurup cevap beklersin, istek attığında tekrar tekrar o servere bir bağlantı kurup sonlandırısın.

onreadystatechange 

bu metod sen istek attıksan sonra state de değişklik olup olmamasına göre çalışır sürekli bir bağlantı yok yani .

2 Beğeni

Anladım sanırım, belirli zaman aralıklı bir döngü oluşturup sürekli sor-cevap al mantığı ile ilerlemek gerekiyor o zaman Ajax’ta. Sadece xhr.onreadystatechange = function bu fonksiyonu setInterval() kullanarak her seferinde txt dosyamızdaki değişikliği sorgluyoruz.
peki bu noktada ki sorum onreadystatechange hangi durumları değişiklik olarak algılıyor?

Tam olarak anlamamışsın galiba. xhr.onreadystatechange request sonucunda çalışır bunun içine interval koyman bir işe yaramaz, tekrar istek atman lazım istek atmayı interval içinde yaparsan olur.

İstediğim şeyi başardım. Başka arkadaşlarında yararlanması için kodların son halini paylaşacağım. İlk başta pür JS ile yapmaya çalıştım ama form gönderme işlerini bir türlü çözemediğim için yarı JQuery yarı vanilla JS oldu.

index2.js

<!DOCTYPE html>

<html lang="tr">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>NodeJS ve AJAX ile çıldırmacalar...</title>

    <style>

        * {

            margin: 0;

            padding: 0;

            box-sizing: border-box;

        }

        body {

            background-color: #ebebeb;

            font: 13px Helvetica, Arial;

        }

        form {

            background: #000;

            padding: 3px;

            position: fixed;

            bottom: 0;

            width: 100%;

        }

        form input {

            border: 0;

            padding: 10px;

            width: 90%;

            margin-right: .5%;

        }

        form button {

            width: 9%;

            background: rgb(168, 73, 73);

            border: none;

            padding: 10px;

        }

       

    </style>

</head>

<body>

    <p>mesajyaz</p>

    <form id="msgformid" action="/" METHOD=POST>

        <input  id="m" NAME="mesaj" autocomplete="off" /><button id="msgbtn" type="submit">Gönder</button>

    </form>

    <script src="public/jquery-3.6.0.js"></script>

   

<script>

     

      // ----Ajax ile form gönderme----

       $('#msgformid').submit(function(event){

        event.preventDefault();  //form gönderildiğinde sayfanın yenilenmesini engelledik

        var gidenmesaj = $('#m').val();

        $.ajax({       //Jquery ayax form gönderme fonksiyonu kullanıyoruz

            url:'/',

            type:'POST',

            data:{mesaj:gidenmesaj},   //app2.js sunucusunda veriyi body.mesaj olarak yakaladığımız için verinin bu şekilde yazılması önemli, yoksa sunucu tarafı tanımsız dönüyor.

            //dataType:'JSON',

            //contentType:arguments,

            //cage:arguments,

            //processData:arguments,

            success:function(data){

                console.log(this.data)

            }

        });

        $('#m').val('');

      });

   //----deneme.txt dosyasından Ajax ile veri çekme işlemleri----

      var xhr = new XMLHttpRequest();

      var etiketsec = document.querySelector('p');    

      window.setInterval(()=>{    //her 1000ms'de bir deneme.txt kontrol edilmesi için bir döngü oluşturduk. Yapmazsak diğer gelen veriden haberimiz olmuyor.

      xhr.onreadystatechange = function () {

        if (this.readyState == 4 && this.status == 200 || this.status == 304) { //bu kontrol hata oluşmaması için şart. burada

            var xmldosyasi= xhr.responseText; //txt dosyasını çekti

            var metinsec = etiketsec.innerHTML; // p etiketinin içeriğini aldık          

            if (metinsec!=xmldosyasi){      // etiket dosyası ile etiket içeriği aynı mı diye karşılaştırdık

              var yenimesaj= xmldosyasi.replace(metinsec,'');  //aynı değilse dosyadan etiket içindeki metini çıkardık, böylece yeni gelen mesaj kalmış oldu

              $('p').append(yenimesaj);   //Yeni mesajı P etiketinin sonuna ekle

            }          

            console.log('yeni mesaj yok');

        };

      };

      xhr.open('GET', 'public/deneme.txt', true); // üstteki işlemlerin yapılabilmesi için ajax isteği

      xhr.send();

      },

      1000);

    </script>

</body>

</html>

app2.js

const express = require('express');

const app = express();

const path = require('path');

const mngs = require('mongoose');

const bodyparser = require('body-parser');

const fs = require('fs');

app.use('/public', express.static(path.join(__dirname, 'public'))); //express.static herkese açık klasörü belirler

app.use(bodyparser.urlencoded({extended:false})); // URL olarak gelen requestleri parçalayarak kullanımını kolaylaştırır

app.use(bodyparser.json({extended:false})); // JSON olarak gelen requestleri parçalayarak kullanımını kolaylaştırır

//mongo ile bağlantı kuruluyor "mongodb://127.0.0.1:27017" ifadesi standarttır. "/chatDB" ise oluşturduğumuz DB ismi

mngs.connect('mongodb://127.0.0.1:27017/chatDB',{ useNewUrlParser: true, useUnifiedTopology: true }, function(err,data){

  if (err){

      console.log('sunucu bağlantı hatası:'+err)

  }else{

  console.log('DB bağlandı...')}

});

//mongoose ile veri göndermek için önce veri tabanı şeması oluşturuyoruz, böylece giden veriler şema ile aynı yapıda DB'ye kaydolacak. "mesajlar" colection ismimizi gösterir

const Schema = mngs.Schema;

let DBsema = new Schema(

  {

  mesaj:String,

  tarih:{type:Date, default:Date.now}

  },

  {

    collection:'mesajlar'

  }

);

let ChatSema = mngs.model('ChatSema', DBsema);

//ana sayfa için index.html sayfasını gönderiyoruz

//Get metodu ile

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

    res.sendFile(__dirname + '/index2.html');

});

//POST metodu ile

app.post('/', function (req, res) {

    res.sendFile(__dirname + '/index2.html');

    console.log('post geldi');

    var varmesaj= req.body.mesaj;

    ChatSema.create({ mesaj:varmesaj }, (err, result) => {

      if (err) throw err;

      console.log(result);

      veriyicek();

    });

});

  //mongoDB'den bütün collectionu çekip son gönderinin mesaj elemanını yakalıyoruz.

 function veriyicek(){

    ChatSema.find({},function(err,data){

    if (err) throw err;

    const DBlemansayisi=data.length;

    const yenidata=DBlemansayisi-1;

    var sonmesajelemani = data[yenidata].mesaj;

    var sontarih = data[yenidata].tarih;

    console.log('  SON    Mesaj elemanı:'+sonmesajelemani);

    //DB'den yakaladığımız son elemanı txt dosyasına yazdırıyoruz

    fs.appendFile('./public/deneme.txt', '<br><h2>'+sonmesajelemani+'</h2>   '+sontarih+'<br>', function (err, data) {

      if (err) throw err;

      console.log('Veri başarıyla yazıldı.');

    });

  });

 };

//sunucu çalışmaya başlar

app.listen(9999, function () {

  console.log('Sunucu çalışıyor...');

});

Yazışma uygulamalarında ki gibi yeni mesajları görebilmek için sayfa hep (scrollbar) en altta olacak şekilde bunu nasıl ayarlayabilirim?