8

divに書き込むAJAX呼び出しについて考えてみます。

recent_req=$.post('result.php', { d: data }, function(returnData) {
    $('#content').html(returnData);
});

PHPスクリプトはresult.php、1ステップあたり約5〜20秒の時間がかかるいくつかの機能を実行します。PHPのflush()関数を使用して、各ステップが開始および終了するとすぐにブラウザーに情報を取得していますが、Javascriptを使用してデータを#contentdivに書き込むにはどうすればよいですか?

ありがとう。

編集: 明確にするために:result.php次のように見え、制約のために実際にはリファクタリングできないと仮定します:

<?php

echo "Starting...<br />";
flush();

longOperation();
echo "Done with first long operation.<br />";
flush();

anotherLongOperation();
echo "Done with another long operation.<br />";
flush();

?>

result.phpエコーステートメントが#content入ってくるときにdivに追加されるように、AJAXをどのように構成して呼び出すことができますか?jQueryを使用する/使用しないソリューションは大歓迎です。ありがとう!

4

7 に答える 7

5

There's a technique using an iframe which you could use to achieve this.

Similar to other suggestions involving frames but it doesn't involve sessions or polling or anything, and doesn't need you to display the iframe itself. It also has the benefit of running any code you want at any point in the process, in case you're doing something more sophisticated with your UI than just pushing text to a div (e.g. you could update a progress bar).

Basically, submit the form to a hidden iFrame then flush javascript to that frame, which interacts with functions in the iFrame's parent.

Like this:

HTML:

<form target="results" action="result.php" method="post">
<!-- your form -->
<input type="submit" value="Go" />
</form>

<iframe name="results" id="results" width="0" height="0" />
<div id="progress"></div>

Javascript, in your main page:

function updateProgress(progress) {
  $("#progress").append("<div>" + progress + "</div>");
}

result.php:

<?php

echo "<script language='javascript'>parent.updateProgress('Starting...');</script>";
flush();

longOperation();
echo "<script language='javascript'>parent.updateProgress('Done with first long operation.');</script>";
flush();

anotherLongOperation();
echo "<script language='javascript'>parent.updateProgress('Done with another long operation.');</script>";
flush();

?>
于 2012-11-20T15:55:31.807 に答える
4

ユーザーのブラウザにサーバー要求を「リッスン」させることができないため、通常の ajax 呼び出しを使用してデータを「ストリーミング」することはできません。「成功」関数は、データの処理が完了したときにのみ呼び出されます。

ただし、インターネット上で「Ajax Push」について多くの議論があり、HTML5 には、ユーザーのブラウザーがサーバー要求をリッスンするために使用できる websocket オブジェクトがあるようです。構文定義はまだ完全には安定していないため、すぐに変更される可能性があるため、いじりたくはありません。

やりたいことは、ステップ 1 のリクエストをディスパッチし、その戻りを待ってから、ステップ 2 のリクエストをディスパッチすることです。全体的な処理時間に多少のオーバーヘッドが追加されます (そして、はるかに冗長になります) が、いくつかの大きなステップしかない場合は問題なく動作するはずです。ステップの処理にあまり時間がかからない場合は、それを行うべきではありません (通信時間が「実効処理時間」よりも長くなるため)。

編集:たとえば、ユーザーのセッションの進行状況を書き込むこともできます。そうすれば、ステータスの更新を要求してサーバーに定期的に ping を送信できます。このように、小さなステップがたくさんある場合でも、10 秒ごとにリクエストをディスパッチするだけで済み、ステップごとにディスパッチするよりも改善されます。

于 2012-11-12T14:06:03.067 に答える
3

別の解決策として、次の例に示すように、 hiddenformを に送信できます。iframe

<?php

function output_data($data)  {
    echo str_pad($data, 4096, ' ', STR_PAD_RIGHT) . "\n";
    flush(); 
}

function long_runner() {        
    output_data("");

    output_data(date("H:i:s").' - Starting...<br />');
    sleep(10);

    output_data(date("H:i:s").' - Done with first long operation.<br />');
    sleep(10);

    output_data(date("H:i:s").' - Done with another long operation.<br />');
    return("<script>parent.task_complete()</script>");
}

if (isset($_REQUEST["status"])) {
    die(long_runner());
}

?>
<!DOCTYPE html>
<html>
    <head>
        <title>Write to IFRAME as data streams in</title>
        <style>
        #myform { display: none }
        #frm { width: 50% }
        </style>
        <script language="javascript" type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
        <script>
        function task_complete() {
            alert('Task completed');
        }

        $(document).ready(function() { 
            $('#starter').click(function() {
                $('#myform').submit();
            });
        });
        </script>
    </head>
    <body>
        <form id="myform" method="get" target="frm" action="<?= $_SERVER['SCRIPT_NAME'] ?>">
            <input type="hidden" name="status" value="0">
        </form>
        <a href="#" id="starter">Start</a><br />
        <iframe id="frm" name="frm" frameborder="0"></iframe>
    </body>
</html>
于 2012-11-14T22:12:16.923 に答える
3

動的データ ストリームを div に書き込む:

ここに行きます..データストリームを「div」に動的に書き込む方法を具体的に尋ねました。多くの人が言っているように、iframe に動的に書き込むことは可能であり、さらに一歩進める必要があります。問題の完全な解決策は次のとおりです。これにより、最大 0.5 秒の遅延でそのデータが div に戻されます。より迅速な更新が必要な場合は、適応させることができます。

<!DOCTYPE html>
<html>
<head>
    <title>dynamic listener</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script type="text/javascript">
    var count;
    $(function(){
        $('#formx').submit(function(){
            setTimeout(function(){ check_div(); }, 500);
            count = 0;
            return true;
        });
    });

    function check_div()
    {
        var $iframetxt = $('#iframex').contents().text();
        var $div = $('#dynamic');
        if( $iframetxt != $div.text() )
        {
            console.log('rewritten!');
            $div.text( $iframetxt );
            setTimeout(function(){ check_div(); }, 500);
            count = 0;
        }
        else
        {
            count++;
            if(count < 40) setTimeout(function(){ check_div(); }, 500);
            else console.log('timed out');
        }       
    }
    </script>
</head>
<body>
    <div>
        Form
        <form id="formx" action="result.php" method="post" target="iframex">
            <input type="submit" />
        </form>
    </div>
    <div id="dynamic"></div>
    <iframe id='iframex' name="iframex" style="display:none" ></iframe>
</body>
</html>

1. フォームの送信時に、ストリーミング データが iframe に送信されます。

このために、form タグの target 属性を iframe 名に設定するだけです。

2. check_div() は 0.5 秒ごとに実行され、#dynamic div のテキストを iframe のテキスト コンテンツと比較します。

それらの間に違いがある場合、データは div に書き込まれ、タイムアウトが再度呼び出されます。差がない場合、タイムアウト カウンタが増加します。カウントが 40 (40 x .5 秒 = 20 秒) 未満の場合、タイムアウトを再度呼び出します。そうでない場合は、ストリームが完了したと見なされます。

于 2012-11-16T21:21:39.833 に答える
2

セッションでのポーリングを使用したソリューションは次のとおりです。

HTML:

<!DOCTYPE html>
<html>
<body>
    <div id="content"></div>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script>
    var pollTimeout;
    function pollResult(){
        $.get('poll.php', function(response) {
            // Update #content with partial response
            $('#content').html(response);
            pollTimeout = setTimeout(pollResult, 1000);
        });
    }
    $.post('result.php', function(response) {
        // Result is loaded, stop polling and update content with final response
        clearTimeout(pollTimeout);
        $('#content').html(response);
    });
    // Start polling
    pollResult();
    </script>
</body>

</html>

結果 PHP:

<?php

class SemiStream{

    public function __construct(){
        @session_start();
        $_SESSION['semi_stream'] = '';
    }

    public function write($data){
        @session_start();
        $_SESSION['semi_stream'] .= $data;
        // We have to save and close the session to be
        // able to read the contents of it in poll.php
        session_write_close();
    }

    public function close(){
        echo $_SESSION['semi_stream'];
        unset($_SESSION['semi_stream']);
    }
}

$stream = new SemiStream();
$stream->write("Starting...<br />");

sleep(3);

$stream->write("Done with first long operation.<br />");

sleep(3);

$stream->write("Done with another long operation.<br />");
$stream->close();

echo 'Done.';

ポーリング PHP:

<?php
session_start();
echo $_SESSION['semi_stream'];

これは、PHP の出力バッファリングを使用しなくても機能します。

于 2012-11-14T23:46:43.080 に答える
0

おそらく、問題はアプリにプッシュ テクノロジを実装する方法についてです。例で素晴らしい答えがあるこの質問を見ることをお勧めします

于 2012-11-19T13:07:04.540 に答える
0

Pusher サービスをチェックしてみてください

于 2012-11-15T20:34:04.820 に答える