8

私はここで少し悪夢を見ているので、助けていただければ幸いです! まず、私がやろうとしていることを説明します。

ここで説明されているようなシステムを実装しようとしています: https://stackoverflow.com/a/1086448/1034392 Yii フレームワークを使用して私のローカルホスト MAMP サーバーに。DB に新しい通知があるかどうかをチェックする関数があります。ある場合は、それらを解析し、json でエンコードします。この関数は、5 秒ごとに while ループで呼び出されます。

したがって、 /user/unreadNotifications に移動すると、次のトリガーが発生します

    Yii::log('test'); // to check it's getting called  

    $this->layout=false;

    header('Content-Type: application/json');

    // LONG POLLING 
    while (Yii::app()->user->getNotifications() == null) {
        sleep(5);
    }

    echo Yii::app()->user->getNotifications(); // prints out json if new notification

    Yii::app()->end();

    return;

これは正常に動作します - ブラウザのリンクに移動し、json 応答を確認しました - すべて問題ありません。

次に、あらゆる種類のjQueryを試して動作させました...動作することがわかった唯一の方法は$.ajax、POSTタイプで使用することですが、待機中の通知がある場合にのみです(したがって、jsonが返されます)。$.getまたは$.post「中止」されます(firebugに表示されます)が、URLが呼び出されます(ログファイルが更新されていることがわかるため)-奇妙な。

使用している私の元のセットアップ$.getは次のとおりです。

        <script type="text/javascript">
            function notificationPoll() {
                $.get('<?php echo Yii::app()->createUrl('user/unreadNotifications') ?>','', function(result) {
                    $.each(result.events, function(events) {
                        alert('New Notification!');
                    });
                    notificationPoll();
                }, 'json');
            }
        </script>

        <script type="text/javascript">
            $(document).ready(function() {
                $.ajaxSetup({
                    timeout: 60 //set a global ajax timeout of a minute
                });
                notificationPoll();
            });
        </script>

これは、何らかの理由で「中止」されます。CORSリクエストではありませんが、「jsonp」で試しましたが、うまくいきません。

これではどこにも行けないようです!誰でも参加できますか?

どうもありがとう

4

4 に答える 4

3

関数が妥当な時間内に終了することを確認する必要があります。あなたができることはこれです:

$ttl = 10;
while ($ttl--) {
    $json = Yii::app()->user->getNotifications();
    if (null != $json) {
        break;
    }
    sleep(1);
}
if (null == $json) {
    $json = json_encode(array(
        'nothing' => true
    ));
}
header('Content-Type: application/json');
echo $json;

Yii::app()->end();
return;

setInterval() を使用して、ポーリング関数をタイマーとして設定します。関数は、たとえば 10 秒ごとに呼び出されるようになり、前の反復が戻る前に呼び出されないようにセマフォを設定する必要がある場合があります。

var timer = setInterval(
    function() {
        if (this.calling) {
            return;
        }
        var fn = this;
        fn.calling = true;
        $.post(url)
         .done(function(data) {
            ..
         })
         .always(function() {
            fn.calling = false;
         });
    },
    10000
);

次に、AJAX のポーリング関数は、( .done()) コールバックで) 通知が存在することを確認する必要があります。

function(data) {
    if (data.hasOwnProperty('nothing')) {
        alert('No notifications');
        return;
    }
    console.log(data);
    ...
}

ここで重要なことの 1 つは、通知がどのように表示されるかです。ここでは、JSON でエンコードされたstringであると想定しています。しかし、代わりに Yii 関数が返すのが配列またはオブジェクトである場合は、そのエンコーディングを処理する必要があります。これは、IF なしでさらにクリーンになる可能性があります。

header('Content-Type: ...
die(json_encode(
    array(
        'status'         => 'success',
        'notification'   => $json /* This is NULL or an array */
    )
    // Javascript side we check that data.notification is not null.
));

デコードはすでに jQuery によって処理されているため、上記の変数 "data" は既に Javascript オブジェクトになっているため、 を呼び出す必要はありませんJSON.parsedata ただし、それがオブジェクトであり、期待されるプロパティを持っていることを確認できます。これにより、エラーが警告されます。

別のページへのナビゲーションを処理するにsetInterval()は、ポーリング Javascript 関数の提供されたタイマー ID をグローバル変数に格納し、ページがonUnload()ポーリングを非アクティブ化するために呼び出したときにタイマーを削除します。

于 2016-10-23T12:02:54.930 に答える
2

通知がない場合、getNotifications は何を返しますか? jQuery は JSON 形式が返されることを想定していますが、空の文字列をエコーするだけでは、応答の形式が JSON ではないため、リクエストは失敗します。毎回 JSON 文字列をエコーするようにしてください。

于 2012-07-02T16:12:16.217 に答える
2

これはどう。$.(get) は notificationPoll(); という関数にあると思います。完了すると再度呼び出されます。

$.ajax({
    url: event_feed_href,
    async: false,
    timeout: 60000,
    done: function(data) {
            var got_json=false;
            try {
                var json = JSON.parse(data);
                got_json=true;
            }
            catch(e) {
                // failed to return JSON data
                alert('Wierd!');
            } 
            if(got_json) {
                // process json data
                alert('New Notification!');
            }
        },
    always: function() {
            notificationPoll();
        }
    });

jQueryが言うように、私はdoneとalways hereを使用しましたが、成功を減価償却しています:失敗:

于 2012-07-02T16:34:31.660 に答える
1

コードの中止に興味があります。あなたの答えがあるかもしれません。複数の理由で発生する可能性があります

  • Query.get が失敗しました。Ajax 呼び出しは何らかの理由で機能しません。解析エラー。
  • JavaScript 構文が正しくありません。例: 成功ハンドラーのコードは、true ではない可能性がある入力引数の events プロパティを想定しています。

jQuery.get の場合、jQuery.get ( https://api.jquery.com/jQuery.get/ ) のドキュメントで提案されているように、関数は暗黙のうちに失敗する可能性があります。.ajaxError を使用して、get が失敗しているかどうかを確認することをお勧めします。 .

jQuery.get() を使用したリクエストがエラー コードを返す場合、スクリプトがグローバルな .ajaxError() メソッドも呼び出していない限り、エラーは表示されずに失敗します。あるいは、jQuery 1.5 以降では、jQuery.get() によって返される jqXHR オブジェクトの .error() メソッドもエラー処理に使用できます。

JavaScript 構文エラーについては、firebug デバッガーをステップ実行することをお勧めします。成功ハンドラーの最初の行にブレークポイントを追加し、そこから各行をステップ実行します。面倒ですが、うまくいきます。

于 2016-10-29T02:40:25.920 に答える