web-dev-qa-db-ja.com

window.stop()を使用せずにイメージ<img>の読み込み要求を中止するにはどうすればよいですか

ユーザーがスクロールすると画像が動的にロードされる非常に長いページがあります。

ただし、ユーザーがページの特定の部分からすばやくスクロールした場合、ページの現在表示されていない部分で画像の読み込みを続行したくありません。

画像の読み込みとは別に、ページ上で同時に発生する他の多くのリクエストがあります。そのため、スクロールイベントで発生する鈍いwindow.stop()は受け入れられません。

表示されなくなった画像のimg src属性を削除およびクリアしようとしましたが、リクエストはすでに開始されているため、画像はロードされ続けます。

ユーザーがページのその部分を短くスクロールすると、画像srcが塗りつぶされたことを思い出してください。ただし、一度過ぎてしまうと、window.stop()を使用しないと、そのイメージの読み込みを停止できませんでした。 srcのクリアが機能しませんでした。 (クローム&FF)

私が見つけた同様の投稿は近づいていますが、この問題を解決していないようです:

44
Evan

nrabinowitz で述べられているように、あなたがやろうとしているのは間違ったアプローチです。画像の読み込みプロセスを単に「キャンセル」することはできません(src属性を空の文字列に設定すると、 良いアイデアではありません )。実際、たとえできたとしても、サーバーはキャンセルされたデータを継続的に送信し、負荷率を上げて速度を落とすため、事態が悪化するだけです。また、これを考慮してください:

  1. ユーザーがページを上下にスクロールする場合、読み込みの遅延が予想されます。
  2. ページの一部の読み込みを開始する前にタイムアウト遅延(例:200ミリ秒)を設定することはかなり許容できます。また、ページ上で200ミリ秒間隔後に停止してジャンプする回数はどれくらいでしょうか。それが起こっても、ポイント1に戻ります
  3. あなたの画像はどれくらい大きいですか?遅いサーバーでさえ、毎秒数十個の3Kbのサムネイルを提供できます。サイトに大きな画像がある場合は、 lightBox のようないくつかのコンポーネントで低解像度および高解像度の画像を使用することを検討してください

多くの場合、コンピューターの問題は単に設計上の問題です。

**[〜#〜] edit [〜#〜]**

ここにアイデアがあります:

  1. ページには、期待される画像サイズの幅と高さでDIVコンテナが表示されます(スタイル設定にCSSを使用)。各DIVの中に、リンクを追加します。例えば ​​:

    <div class="img-wrapper thumbnail">
       <a href="http://www.domain.com/path/to/image">Loading...</a>
    </div>
    
  2. このJavascriptを追加します(テストされていない、アイデアは自己記述的です)

    $(function() {
    
    var imgStack;
    var loadTimeout;
    
    $(window).scroll(function() {
       imgStack = null;
       if (loadTimeout) clearTimeout(loadTimeout);
    
       loadTimeout = setTimeout(function() {
    
          // get all links visible in the view port
          // should be an array or jQuery object
          imgStack = ...
    
          loadNextImage();
       }, 200);                // 200 ms delay
    });
    
    function loadNextImage() {
       if (imgStack && imgStack.length) {
          var nextLink = $(imgStack.pop());   // get next image element
    
          $('<img />').attr('src', nextLink.attr('href'))
            .appendTo(nextLink.parent())
            .load(function() {
               loadNextImage();
            });
    
          // remove link from container (so we don't precess it twice)
          nextLink.remove();
       }
    };
    
    });
    
17
Yanick Rochon

さて、私の考え:

1)画像のAJAXリクエストを開始し、成功した場合、画像はブラウザキャッシュに移動し、「src」属性を設定すると、画像はキャッシュから表示されます

2)XHRを中止できます

巨大なイメージのダウンロードを高速でエミュレートする小さなサーバーを作成しました(実際には20秒待機してからイメージを返します)。その後、私はこれを私のHTMLに持っています:

<!DOCTYPE html>
<html>
    <head>
        <style>
            img {
                width: 469px;
                height: 428px;
                background-color: #CCC;
                border: 1px solid #999;
            }
        </style>
    </head>

    <body>
        <img data-src="./img" src="" />
        <br />
        <a id="cancel" href="javascript:void(0)">CANCEL</a>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(function () {
                var xhr, img = $('img'), src = img.data('src');

                xhr = $.ajax(src, {
                    success: function (data) { img.attr('src', src) }
                });

                $('#cancel').click(function (){
                    xhr.abort();
                })
            });
        </script>
    </body>
</html>
12
Guard

Ajax呼び出しを使用して画像を読み込むことができます。スクロールアウトを使用する場合は、呼び出しを中止できます。
jQuery擬似コードでは、次のようなものになります(構文の誤りを許してください。これは単なる例です)。

1)ロードする画像にタグを付けます

$(".image").each( function(){
    if ( is_in_visible_area(this) ) { // check [1] for example
        $(this).addClass("load_me");
    } else {
        $(this).addClass("dont_load");
    }
});

2)画像を読み込む

ajax_requests = {};

$(".image.load_me").each( function(){
    // load image
    var a = $.ajax({
        url: 'give_me_photos.php',
        data: {img: photo_id},
        success: function(html){
            photo_by_id(photo_id), img.append(html);
        }
    });
    ajax_requests[photo_id] = a;

});

3)画面外への読み込みをキャンセルする

for( id in ajax_requests ) {
    if ( ! is_in_visible_area(id) ) {
        ajax_requests[id].abort();
    }
}

もちろん、画像が既にロードされているかどうかのチェックも追加します(例えば、クラス「ロード」)

[1]。 スクロール後に要素が表示されるかどうかを確認

[2]。 jQueryを使用してAjaxリクエストを中止する

2
Jakub M.
  1. スタックを使用してAjaxリクエストを管理します(つまり、パラレルではなくシリアルでロードすることになりますが、それだけの価値はあります)

  2. スクロール停止時に、300ms待機してから、ビュー領域内のすべての画像をスタックにプッシュします

  3. ユーザーがスクロールするたびに、スタックが実行されているかどうかを確認します。 (fyi-すべてのajaxコールを殺す代わりに、特定のURLへのすべてのリクエストを停止できます。また、ページ上の他のリクエストを停止しないように正規表現を使用できます)

  4. 既存のスタックが実行されている場合-最上位のスタックを除くすべてのイメージをポップします。

  5. すべてのajax呼び出しで-beforeSend()イベントをバインドして、スタックから特定の画像を削除します

今は遅いですが、仕事で非常に似たようなことをしました。詳細なコードが必要な場合はお知らせください。

乾杯!

1
Varun Vohra

たぶん、ロードを停止することを示すdb(またはより良いのはmemcached)のフィールドをチェックするphpスクリプトを介して画像を提供できます。スクリプトは画像をチャンクに分割し、各チャンクの間に一時停止し、特定のリクエストの停止フラグがそうであるかどうかを確認します。設定されている場合、A 204でヘッダーを送信しますが、ブラウザが取得するとすぐに受信を停止するコンテンツはありません。

ただし、これは少し過剰な場合があります。

0
matthewdaniel

ところで、うまくいくかもしれない別のアイデア:

1)新しいiframeを作成する

2)iframe内には、画像の読み込みを開始するスクリプトがあり、読み込まれたら.parentのメソッドを呼び出します

3)必要に応じて、iframeオブジェクトで.stopを使用してiframeコンテンツの読み込みを停止します

0
Guard

ソリューションはウェブワーカーかもしれません。 Webworkerを終了し、彼と接続することができます。ただし、Webworkerがブラウザの限られた接続を使用するため、アプリケーションがブロックされるという小さな問題があります。

現在、私はserviceWorkersを使用したソリューションに取り組んでいます-接続制限はありません(そうすることを望みます)

0
teter