Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
200 views
in Technique[技术] by (71.8m points)

javascript - PHP Script in IFRAME Blocks Other Code

Scenario:

I have two PHP scripts to be called simultaneously:

  1. The first script will run several minutes (PHP based file download), depending on downloaded file size. It is placed into <iframe> so it can run separately and does not block the browser.
  2. The second PHP script is supposed to be called in regular intervals to monitor execution of the first script - file progress download. To avoid opening new windows upon script completion, it is called via AJAX.

Problem:

I have placed the long-running PHP Script (download script) into <iframe> so this script can run asynchronously with other monitoring PHP script. However, despite the main script is in <iframe>, when the webpage starts execution, the script starts and blocks execution of the remaining JavaScript code and monitoring script called multiple times via AJAX.

It is important to have the short-running monitoring PHP script called simultaneously with the long-running PHP (download) script, so the short-running (monitoring)script can provide feedback to JavaScript.

Would you be so kind and analyze my code samples please? I have no idea, where is my problem. My code is so simple, that everything should be running well.

  • PHP Version 5.4.12
  • Apache/2.4.4 (Win64) PHP/5.4.12
  • Windows 7 x64
  • 8GB RAM
  • Google Chrome Version 30.0.1599.101 m

Code Samples:

JavaScript code calling both PHP scripts:

<!DOCTYPE html>
<html>
<head>
    <title>Title of the document</title>
</head>

<body onload="callScripts();">


<script type="text/javascript">

    // call both PHP scripts(download and monitoring) in desired order
    callScripts = function()
    {
        // call the monitoring PHP script multiple times in 2 second intervals
        window.setTimeout(function(){startDownloadMonitoring()}, 1000);
        window.setTimeout(function(){startDownloadMonitoring()}, 3000);
        window.setTimeout(function(){startDownloadMonitoring()}, 5000);
        window.setTimeout(function(){startDownloadMonitoring()}, 7000);
        window.setTimeout(function(){startDownloadMonitoring()}, 9000);
    };


    // call monitoring PHP script via AJAX
    function startDownloadMonitoring()
    {
        console.log("Calling startDownloadMonitoring()...");

        var xmlhttp;

        if (window.XMLHttpRequest)
        {// code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
        }
        else
        {// code for IE6, IE5
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }

        xmlhttp.onreadystatechange = function()
        {
            if (xmlhttp.readyState==4 && xmlhttp.status==200)
            {
                console.log("Response Received: " + xmlhttp.responseText);
            }
        }
        xmlhttp.open("GET", "PHP/fileDownloadStatus.php", true);
        xmlhttp.send();
    }
</script>

<iframe src="PHP/fileDownload.php"></iframe>

</body>
</html>

PHP Monitoring Script(fileDownloadStatus.php)

<?php

include 'ChromePhp.php';

// start session, update session variable, close session
session_start();
$_SESSION['DownloadProgress']++;
ChromePhp::log('$_SESSION['DownloadProgress'] = ' . $_SESSION['DownloadProgress']);
session_write_close();    

echo "success";
?>

PHP long-running script (fileDownload.php)

<?php
include 'ChromePhp.php';

// disable script expiry
set_time_limit(0);    

// start session if session is not already started
session_start();

// prepare session variables
$_SESSION['DownloadProgress'] = 10;

session_write_close();

for( $count = 0; $count < 60; $count++)
{
    sleep(1);

    print("fileDownload Script was called: ". $count);

    echo "Download script: " . $count;
    ob_flush();
    flush();
}
?>

Screenshot:

PHP Scripts Execution Order - browser waits to finish the script in <iframe> Scripts execution order

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your problem is as simple as you can imagine. You just don't realize it maybe for a bit lack of knowledge of HTML. So Your code is ok and everything is working as you want but the script that should run at the same time isn't, what is the problem?

<body onload="callScripts();">

This up here is your problem. The onload call only takes place when everything inside the body tag is completely loaded. So, as your iframe is inside the body the html interpreter load everything (including the iframe and its source), then call your callScripts function.

To solve your problem I recommend you to create your iframe inside your script. Would be something as this:

<!DOCTYPE html>
<html>
<head>
    <title>Title of the document</title>

    <!-- You should always define your script in the head tag. best pratice
     defined in W3C -->

<script type="text/javascript">

    callScripts = function (){
         //write your Iframe Here
         document.getElementById("callDownload").innerHTML = '<iframe src="PHP/fileDownload.php"></iframe>'; 
         callScripts_refresh();
    }

    // call both PHP scripts(download and monitoring) in desired order
    callScripts_refresh = function()
    {

        // call the monitoring PHP script multiple times in 2 second intervals
        window.setTimeout(function(){startDownloadMonitoring()}, 1000);
        window.setTimeout(function(){startDownloadMonitoring()}, 3000);
        window.setTimeout(function(){startDownloadMonitoring()}, 5000);
        window.setTimeout(function(){startDownloadMonitoring()}, 7000);
        window.setTimeout(function(){startDownloadMonitoring()}, 9000);
    };


    // call monitoring PHP script via AJAX
    function startDownloadMonitoring()
    {
        console.log("Calling startDownloadMonitoring()...");

        var xmlhttp;

        if (window.XMLHttpRequest)
        {// code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
        }
        else
        {// code for IE6, IE5
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }

        xmlhttp.onreadystatechange = function()
        {
            if (xmlhttp.readyState==4 && xmlhttp.status==200)
            {
                console.log("Response Received: " + xmlhttp.responseText);
            }
        }
        xmlhttp.open("GET", "PHP/fileDownloadStatus.php", true);
        xmlhttp.send();
    }
</script>

</head>

<body onload="callScripts();">

<div id="callDownload"></div>

</body>
</html>

Let me know if it work after that


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...