3

シナリオ:

同時に呼び出す 2 つの PHP スクリプトがあります。

  1. 最初のスクリプトは、ダウンロードされたファイルのサイズに応じて、数分間 (PHP ベースのファイル ダウンロード) 実行されます。<iframe>個別に実行でき、ブラウザをブロックしないように配置されています。
  2. 2 番目の PHP スクリプトは、最初のスクリプト (ファイルの進行状況のダウンロード) の実行を監視するために定期的に呼び出されることになっています。スクリプトの完了時に新しいウィンドウが開かないようにするために、AJAX 経由で呼び出されます。

問題:

長時間実行される PHP スクリプト (ダウンロード スクリプト) を に<iframe>配置して、このスクリプトを他の監視 PHP スクリプトと非同期で実行できるようにしました。ただし、メイン スクリプトが にあるにもかかわらず、<iframe>Web ページの実行が開始されると、スクリプトが開始され、AJAX を介して複数回呼び出される残りの JavaScript コードと監視スクリプトの実行がブロックされます。

短時間実行の監視 PHP スクリプトを長時間実行 PHP (ダウンロード) スクリプトと同時に呼び出すことが重要です。これにより、短時間実行 (監視) スクリプトが JavaScript にフィードバックを提供できるようになります。

私のコードサンプルを分析していただけませんか?私の問題はどこにあるのかわかりません。私のコードはとてもシンプルなので、すべてがうまく動作するはずです。

  • PHP バージョン 5.4.12
  • アパッチ/2.4.4 (Win64) PHP/5.4.12
  • ウィンドウズ 7 x64
  • 8GBのRAM
  • Google Chrome バージョン 30.0.1599.101 m

コード サンプル:

両方の PHP スクリプトを呼び出す JavaScript コード:

<!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監視スクリプト(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 長時間実行スクリプト (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();
}
?>

スクリーンショット:

PHP スクリプトの実行順序 - ブラウザはスクリプトの終了を待機します<iframe> スクリプトの実行順序

4

1 に答える 1

3

あなたの問題は想像できるほど単純です。HTML の知識が少し不足している可能性があります。あなたのコードは大丈夫で、すべてが思いどおりに機能していますが、同時に実行する必要があるスクリプトはそうではありません。何が問題なのですか?

<body onload="callScripts();">

これがあなたの問題です。呼び出しは、タグ内のすべてが完全にロードされたonloadときにのみ行われます。bodyしたがって、 html インタープリターiframe内にあるので、bodyすべて (iframe とそのソースを含む) をロードしてから、callScripts関数を呼び出します。

問題を解決するにはiframe、スクリプト内に作成することをお勧めします。次のようになります。

<!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>

その後、うまくいったら教えてください

于 2013-10-31T02:20:05.013 に答える