Вместо бесконечного опроса с использованием XMLHttpRequest
- где каждая из включаемых страниц предназначена для запуска запросов каждую секунду для получения одних и тех же данных, одна альтернатива, которую вы могли бы sh рассмотреть, - это использовать EventSource
соединение в сочетании с postMessage
В приведенном выше коде вы надеетесь включить две страницы box
в родительскую страницу (append2.html
), но это будет недействительно как страница HTML может иметь только один раздел HTML
, HEAD
и BODY
, поэтому включение целых веб-страниц внутри элементов DIV - это не способ продолжить - вместо этого очевидным выбором было бы использовать элементы iframe
, которые загружают другие страницы. В демонстрации ниже эти окна iframe статически загружают страницы box1, box2, но вы можете загружать их динамически.
Для mimi c вашей настройки задействовано 5 страниц: -
sse.php ~ the file that reads the textfile every N seconds and sends data back
push.php ~ form that allows user to update text file with new number
append2.html ~ two statically declared iframes, content populated using `postMessage`
box1.html, box2.html ~ identical pages that `listen` for messages from append2.html
sse. php
<?php
set_time_limit( 0 );
ini_set('auto_detect_line_endings', 1);
ini_set('max_execution_time', '0');
ob_end_clean();
$sleep=1; # send data every $sleep seconds
$evt='txtupdate'; # Event name used in Javascript
$file='m_data.txt'; # read this file for updated number
#utility method to send formatted data
function sse( $evtname='iss', $data=null, $retry=1000 ){
if( !is_null( $data ) ){
echo "event:".$evtname."\r\n";
echo "retry:".$retry."\r\n";
echo "data:" . json_encode( $data, JSON_FORCE_OBJECT );
echo "\r\n\r\n";
}
}
# headers... consider modifying `Allow-Origin` to increase security
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Access-Control-Allow-Origin: *' );
#infinite loop - read file and send data payload
while( true ){
if( connection_status() != CONNECTION_NORMAL or connection_aborted() ) break;
$payload=[
'count' => intval( file_get_contents( $file ) )
];
call_user_func( 'sse', $evt, $payload );
/* -- Send output -- */
if( @ob_get_level() > 0 ) for( $i=0; $i < @ob_get_level(); $i++ ) @ob_flush();
@flush();
sleep( $sleep );
$payload = null;
}
if( @ob_get_level() > 0 ) {
for( $i=0; $i < @ob_get_level(); $i++ ) @ob_flush();
@ob_end_clean();
}
?>
pu sh. php
<?php
$file='m_data.txt'; # read & update this file ( same as referenced in SSE )
$autoupdate=true; # does the user need to manually update the number in the form?
$int=file_exists( $file ) ? intval( file_get_contents( $file ) ) : 0;
if( $_SERVER['REQUEST_METHOD']=='POST' && isset( $_POST['action'] ) ){
ob_clean();
$json=[];
if( $_POST['action'] == 'update-file' ){
$number=intval( $_POST['number'] );
if( $autoupdate ) $number++;
file_put_contents( $file, $number );
$json=json_encode( array( 'number'=>$number ) );
}
exit( $json );
}
?>
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>push</title>
<script>
/*
send ajax request to server, update source textfile
and return the new count. Use the callback to update
the displayed number.
*/
document.addEventListener('DOMContentLoaded',(e)=>{
let form=document.forms.push;
let bttn=form.querySelector('[type="button"]');
bttn.addEventListener('click',()=>{
let fd=new FormData( form );
fd.append('action','update-file');
fetch( location.href, { method:'post',body:fd } )
.then( r=>{ return r.json() })
.then( json=>{
form.number.value=json.number;
})
});
})
</script>
</head>
<body>
<form name='push'>
<label>Number: <input type='number' name='number' value='<?=$int;?>' /></label>
<?php
if( $autoupdate ){
echo "
<p>You do NOT need to manually update this number - simply click the button to increment the counter by 1</p>";
}
?>
<input type='button' value='Update' />
</form>
</body>
</html>
append2. html
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Display</title>
<style>
iframe{
width:30%;
margin:1rem;
border:5px dashed rgba(100,100,100,0.25);
border-radius:1rem;
background:whitesmoke;
padding:0;
}
</style>
<script>
let evtsource = new EventSource( 'sse.php', { withCredentials: false } );
evtsource.addEventListener( 'txtupdate', function(e){
if( !e.origin == window.location.origin ) return false;
let json=JSON.parse( e.data );
let b1=document.getElementById('b1').contentWindow;
let b2=document.getElementById('b2').contentWindow;
b1.postMessage( json.count );
b2.postMessage( json.count );
});
</script>
</head>
<body>
<!-- box 1 -->
<iframe id='b1' src='box1.html'></iframe>
<!-- box 2 -->
<iframe id='b2' src='box2.html'></iframe>
</body>
</html>
box1 & box2
<!DOCTYPE html>
<html lang='en'>
<head>
<title>Box 1||Box 2</title>
<script>
window.addEventListener( 'message', (e)=>{
if( e.origin == window.location.origin ){
document.getElementById('liveDataM').textContent=e.data;
}
});
</script>
</head>
<body>
<div id='liveDataM' class='relative anim my_textBold'></div>
</body>
</html>
Откройте две вкладки браузера - загрузите push.php
в одну и append2.html
в другую и обновите текстовый файл, чтобы увидеть значение, отображаемое одновременно в обоих фреймах. Надеюсь, это поможет /