Код плохо запускается в режиме реального времени. Как исправить?
Вложений: 3
У меня есть json документ, в отдельном файле я его подгружаю с помощью ajax, потом вношу в него изменения и сохраняю повторно. Смысл работы скрипта заключается в следующем. Есть “посты” в них вложены картинки, у каждого поста существует статус который принимает три значение “ok”, “wait” и “current”. У картинок тоже есть эти статусы. В каждом посте может быть несколько картинок.
В итоге скрипт каждую секунду открывает ветку поста проходит по картинкам и всем присваивает статус ok, дальше когда все картинки у поста закончились и они получили свой статус ok, главному посту также присваивается status ok и так до конца json документа. Вот пример на картинке, как это работает. Вложение 4792 Проблема заключается в следующем скрипт плохо работает в режиме реального времени. Т.е. при первом запуске ничего не происходит. Я достаточно долго пыталась разобраться в чем ошибка. Пока не связалась с json документом, указав в браузере прямой путь, и не обновила этот документ. Пример на картинки. Вложение 4793 После обновления в открытом окне скрипт сразу стал работать в реальном времени. В чем здесь может быть проблема? Я забыла указать в php заголовок или что-то другое? Мой код: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>Example Json</title> <style> body { font-family: sans-serif; } #output{background-color:rgba(194,194,194,0.6);position:fixed;top:15px;right:115px;z-index:2;} </style> </head> <body> <div id="output"> <strong>true</strong> </div> <div id="tree"></div> <script> var bool = false; var Index1 = 0; var jsontent; var bool = false; var posts; const recursiveList = ((ul, li, data, color = {"current" : "#767474", "wait" : "#E51012", "ok" : "#1DDD32"}) => { const html = Object.entries(data).map(([key, value]) => { const item = li.cloneNode(); item.textContent = `[${key}]`; if(key === "status") item.style.backgroundColor = color[value]; if(key === "photo") color = {"current" : "#808080", "wait" : "#FF0000", "ok" : "#00FF00"}; value = (typeof value === "object") ? recursiveList(value, color) : ` ${value}`; item.append(value); return item; }); const list = ul.cloneNode(); list.append(...html); return list; }).bind(null, document.createElement("UL"), document.createElement("li")); function init() { Index1 = -1; bool = true; setInterval(test,1000); } init(); var output = document.getElementById('output'); var i = 0; function test() { ajaxQuery(); } function ajaxQuery() { var ajaxhttp = new XMLHttpRequest(); var url = "./data.json"; ajaxhttp.open("GET",url,true); ajaxhttp.setRequestHeader("content-type","application/json"); ajaxhttp.onreadystatechange = function(){ if(ajaxhttp.readyState == 4 && ajaxhttp.status == 200){ //console.log(ajaxhttp.responseText); jsontent = JSON.parse(ajaxhttp.responseText); tree.innerHTML = ""; const html = recursiveList(jsontent); tree.append(html); output.innerHTML = "<strong>"+bool+"</strong> " + i +" == "+Index1; posts = jsontent["response"]; if(bool) { switch(Index1) { case -1: // if (x === 'value1') posts[i].status = "current"; break; default: if(posts.length-1<i) { i = 0; } if(Index1 >= posts[i].photo.length) { posts[i].status = "ok"; i++; Index1 = -2; } else { posts[i].photo[Index1].big.status = "ok"; } if(posts[i]==undefined) { bool = false; } break; } jsontent["response"] = posts; const jsonString = JSON.stringify(jsontent); const xhr = new XMLHttpRequest(); xhr.open("POST",'receive.php'); xhr.setRequestHeader("Content-Type","application/json"); xhr.send(jsonString); Index1++; } } } ajaxhttp.send(); } </script> </body> </html> Код php: <?php $requestPayload = file_get_contents("php://input"); $object = json_decode($requestPayload,true); $myFile = "data.json"; file_put_contents($myFile,$requestPayload); ?> Прикладываю также исходники: Вложение 4794 |
Olga27,
может выкинуть setInterval и забыть об этом методе навсегда, а запускать запрос через setTimeout, когда придёт ответ с сервера. |
У вас просто файлик кешируется, либо отключите кеширование вовсе, либо сделайте так, чтобы клиент загружал новую версию файла, если он изменился (почитайте про etag).
p.s. код php - моё почтение. |
Я не знаю в чем дело по прежнему, не работает в режиме реального времени, код setInterval я заменила на setTimeout, как советовали выше.
Вот пример: function init() { Index1 = -1; bool = true; var timer = setTimeout(function ajaxQuery(){ var ajaxhttp = new XMLHttpRequest(); var url = "./data.json"; ajaxhttp.open("GET",url,true); ajaxhttp.setRequestHeader("content-type","application/json"); ajaxhttp.onreadystatechange = function(){ if(ajaxhttp.readyState == 4 && ajaxhttp.status == 200){ //console.log(ajaxhttp.responseText); jsontent = JSON.parse(ajaxhttp.responseText); tree.innerHTML = ""; const html = recursiveList(jsontent); tree.append(html); output.innerHTML = "<strong>"+bool+"</strong> " + i +" == "+Index1; posts = jsontent["response"]; if(bool) { switch(Index1) { case -1: // if (x === 'value1') posts[i].status = "current"; break; default: if(posts.length-1<i) { i = 0; } if(Index1 >= posts[i].photo.length) { posts[i].status = "ok"; i++; Index1 = -2; } else { posts[i].photo[Index1].big.status = "ok"; } if(posts[i]==undefined) { bool = false; } break; } jsontent["response"] = posts; const jsonString = JSON.stringify(jsontent); const xhr = new XMLHttpRequest(); xhr.open("POST",'receive.php'); xhr.setRequestHeader("Content-Type","application/json"); xhr.send(jsonString); Index1++; } } } ajaxhttp.send(); setTimeout(ajaxQuery,1000); },1000); //setInterval(test,1000); } Также php файл я тоже изменила: <?php $myFile = "data.json"; $last_modified = filemtime( $myFile ); $modified_since = ( isset( $_SERVER["HTTP_IF_MODIFIED_SINCE"] ) ? strtotime( $_SERVER["HTTP_IF_MODIFIED_SINCE"] ) : false ); $etagHeader = ( isset( $_SERVER["HTTP_IF_NONE_MATCH"] ) ? trim( $_SERVER["HTTP_IF_NONE_MATCH"] ) : false ); $requestPayload = file_get_contents("php://input"); $object = json_decode($requestPayload,true); $etag = sprintf( '"%s-%s"', $last_modified, md5( $myFile ) ); header( "Last-Modified: ".gmdate( "D, d M Y H:i:s", $last_modified )." GMT" ); header( "Etag: ".$etag ); if ( (int)$modified_since === (int)$last_modified && $etag === $etagHeader ) { header( "HTTP/1.1 304 Not Modified" ); exit; } file_put_contents($myFile,$requestPayload); ?> |
const url = `полный веб путь к файлу data.json?v=${performance.now()}`; |
Цитата:
Вам нужно добавить etag к вашему data.json файлу, а не к файлу, который принимает post-запросы. |
Цитата:
<?php $myFile = "data.json"; $last_modified = filemtime( $myFile ); .... |
Цитата:
|
Цитата:
const url = `полный веб путь к файлу data.json?v=${performance.now()}`; Ответ уже написал. Каждый раз запрашиваем новый урл с разными параметрами. Ни браузер, ни сервера кешировать запросы не будут добавьте любой рандомный параметр к запросу как в примере |
Не знаю, как это работает, но есть предположение. Возможно получение json файла напрямую происходит быстрее, чем получение json-файла через php обработчик.
Получаю json файл и отправляю его на рhp для записи, в итоге php не успевает выполнить скрипт и json снова вызывается со старыми данными, поэтому ничего не работает. Вообщем я сделала вызов и запись json через php. Теперь работает, а все остальные варианты нет: function file_exists(url1) { var text = ""; $.get(url1) .done(function() { $('#flag').text("true"); }).fail(function() { //text = "Файл не существует"; $('#flag').text("false"); }); } function init() { Index1 = -1; bool = true; var timer = setTimeout(function ajaxQuery(){ var ajaxhttp = new XMLHttpRequest(); // var url = 'http://3json_example.su/data.json?v=${performance.now()}'; //file_exists(url); ajaxhttp.open("POST","http://3json_example.su/ex.php", true); ajaxhttp.onreadystatechange = function(){ if(ajaxhttp.readyState == 4 && ajaxhttp.status == 200){ //console.log(ajaxhttp.responseText); jsontent = JSON.parse(ajaxhttp.responseText); tree.innerHTML = ""; const html = recursiveList(jsontent); tree.append(html); output.innerHTML = "<strong>"+bool+"</strong> " + i +" == "+Index1; posts = jsontent["response"]; if(bool) { switch(Index1) { case -1: // if (x === 'value1') posts[i].status = "current"; break; default: if(posts.length-1<i) { i = 0; } if(Index1 >= posts[i].photo.length) { posts[i].status = "ok"; i++; Index1 = -2; } else { posts[i].photo[Index1].big.status = "ok"; } if(posts[i]==undefined) { bool = false; } break; } console.log(posts); jsontent["response"] = posts; const jsonString = JSON.stringify(jsontent); const xhr = new XMLHttpRequest(); xhr.open("POST",'receive.php'); xhr.setRequestHeader("Content-Type","application/json"); xhr.send(jsonString); Index1++; } } } ajaxhttp.send(); setTimeout(ajaxQuery,1000); },1000); //setInterval(test,1000); } Файл ex.php <?php $last_modified = filemtime( __FILE__ ); $modified_since = ( isset( $_SERVER["HTTP_IF_MODIFIED_SINCE"] ) ? strtotime( $_SERVER["HTTP_IF_MODIFIED_SINCE"] ) : false ); $etagHeader = ( isset( $_SERVER["HTTP_IF_NONE_MATCH"] ) ? trim( $_SERVER["HTTP_IF_NONE_MATCH"] ) : false ); $data = file_get_contents("data.json"); $etag = sprintf( '"%s-%s"', $last_modified, md5( $data ) ); header( "Last-Modified: ".gmdate( "D, d M Y H:i:s", $last_modified )." GMT" ); header("Content-Type: text/html; charset=utf-8"); header( "Etag: ".$etag ); if ( (int)$modified_since === (int)$last_modified && $etag === $etagHeader ) { header( "HTTP/1.1 304 Not Modified" ); exit; } echo $data; ?> P.S. Хотя я протестировала во всех браузерах, через некоторое время еще раз протестирую чтобы убедиться, что все работает. |
Часовой пояс GMT +3, время: 01:52. |