2012-02-06 3 views
0

私は最近、私のサイトの検索結果に評価システムを提供するための素晴らしいmootoolsプラグインをダウンロードしました:MooStarRating資産の画像が遅い?ブラウザをフリーズしないように関数を実行するにはどうすればよいですか?

非常にうまく動作しますが、初期化するのが非常に遅いです。ここに私が記録した実行時間(50の検索結果を取り戻すためのもの)があります。ここで

======== starrating ======== 
init:  0.06ms 50 
img:  5.40ms 50 
str:  0.54ms 50 
each:  3.04ms 50 
inject: 0.86ms 50 
end:  1.52ms 50 
subtotal: 11.42ms 50 
----------------- 
total: 571.00ms 

は、これらのログは、(ちょうど参照用)を参照してくださいinitialize機能である:

initialize: function (options) { 

    lstart("starrating"); 

    // Setup options 
    this.setOptions(options); 

    // Fix image folder 
    if ((this.options.imageFolder.length != 0) && (this.options.imageFolder.substr(-1) != "/")) 
     this.options.imageFolder += "/"; 

    // Hover image as full if none specified 
    if (this.options.imageHover == null) this.options.imageHover = this.options.imageFull; 

    lrec("init"); 

    // Preload images 
    try { 
     Asset.images([ 
     this.options.imageEmpty, 
     this.options.imageFull, 
     this.options.imageHover 
    ]); 
    } catch (e) { }; 

    lrec("img"); 

    // Build radio selector 
    var formQuery = this.options.form; 
    this.options.form = $(formQuery); 
    if (!this.options.form) this.options.form = $$('form[name=' + formQuery + "]")[0]; 
    if (this.options.form) { 
     var uniqueId = 'star_' + String.uniqueID(); 
     this.options.form.addClass(uniqueId); 
     this.options.selector += 'form.' + uniqueId + ' '; 
    } 
    this.options.selector += 'input[type=radio][name=' + this.options.radios + "]"; 
    // Loop elements 
    var i = 0; 
    var me = this; 
    var lastElement = null; 
    var count = $$(this.options.selector).length; 
    var width = this.options.width.toInt(); 
    var widthOdd = width; 
    var height = this.options.height.toInt(); 
    if (this.options.half) { 
     width = (width/2).toInt(); 
     widthOdd = widthOdd - width; 
    } 

    lrec("str"); 

    $$(this.options.selector).each(function (item) { 

     // Add item to radio list 
     this.radios[i] = item; 
     if (item.get('checked')) this.currentIndex = i; 

     // If disabled, whole star rating control is disabled 
     if (item.get('disabled')) this.options.disabled = true; 

     // Hide and replace 
     item.setStyle('display', 'none'); 
     this.stars[i] = new Element('a').addClass(this.options.linksClass); 
     this.stars[i].store('ratingIndex', i); 
     this.stars[i].setStyles({ 
      'background-image': 'url("' + this.options.imageEmpty + '")', 
      'background-repeat': 'no-repeat', 
      'display': 'inline-block', 
      'width': ((this.options.half && (i % 2)) ? widthOdd : width), 
      'height': height 
     }); 
     if (this.options.half) 
      this.stars[i].setStyle('background-position', ((i % 2) ? '-' + width + 'px 0' : '0 0')); 
     this.stars[i].addEvents({ 
      'mouseenter': function() { me.starEnter(this.retrieve('ratingIndex')); }, 
      'mouseleave': function() { me.starLeave(); } 
     }); 

     // Tip 
     if (this.options.tip) { 
      var title = this.options.tip; 
      title = title.replace('[VALUE]', item.get('value')); 
      title = title.replace('[COUNT]', count); 
      if (this.options.tipTarget) this.stars[i].store('ratingTip', title); 
      else this.stars[i].setProperty('title', title); 
     } 

     // Click event 
     var that = this; 
     this.stars[i].addEvent('click', function() { 
      if (!that.options.disabled) { 
       me.setCurrentIndex(this.retrieve('ratingIndex')); 
       me.fireEvent('click', me.getValue()); 
      } 
     }); 

     // Go on 
     lastElement = item; 
     i++; 

    }, this); 

    lrec("each"); 

    // Inject items 
    $$(this.stars).each(function (star, index) { 
     star.inject(lastElement, 'after'); 
     lastElement = star; 
    }, this); 

    lrec("inject"); 

    // Enable/disable 
    if (this.options.disabled) this.disable(); else this.enable(); 

    // Fill stars 
    this.fillStars(); 

    lrec("end"); 

    return this; 
}, 

ので、機能の最も遅い部分はこれです:

// Preload images 
    try { 
     Asset.images([ 
     this.options.imageEmpty, 
     this.options.imageFull, 
     this.options.imageHover 
    ]); 
    } catch (e) { }; 

奇妙はどれ。 Asset.imagesは何をしますか?これらの画像がブラウザによってロードされるまでスクリプトはブロックされますか?より速く動くイメージをプリロードする方法はありますか?

ページのスクリプトをより高速に実行するにはどうすればよいですか?実行に800msかかるのは大きな問題ですが、200msはまだかなり悪いです。現時点では、私の検索結果はすべてすぐに現れます。個々の検索結果を個別に作成して、作成中にブラウザをブロックしないようにすることは可能ですか?同様に、MooStarRatingプラグインなど、検索結果の個々のコンポーネントに対してこれを行うことは可能ですか?

答えて

1

いいえ。 Asset.imagesは、それぞれが別々にロードされ、すべての完了時に単一のイベントが送出されるため、非ブロッキングです。

ロード速度はブラウザに依存しますが、同じホストからパラレルにダウンロードするためにどのような機能にもマルチスレッド化されます。

https://github.com/mootools/mootools-more/blob/master/Source/Utilities/Assets.js#L115-129

すぐに、それはまだ、ダウンロードすることができる要素のPROMISEと要素のコレクションを返します。それはうまくいきます - それを使用してelsを挿入したり、イベントやクラスを添付したりすることができます。

個々の画像は、それがonProgressを発射し、すべてが終わったときに、たくさんのためonCompleteそのonload自分のしている - 私は、それを可能にするために、あなたに助言try/catchブロックを削除し、遅延を作成された画像見るであろう。確かにAsset.imagesから戻ってくるものを待つ必要はありません。

あなたはまた、実際にはクラスインスタンスへの参照を保存していないので、何よりも「プライムキャッシュ」メソッドとして使用しているようです。あなたの 'each'反復は恐らくオブジェクトと関数がキャッシュされているので参照の半分の時間を使うように最適化することができます。イベントの委任を使用できる場合はおそらくさらに多くなります。

javascriptのシングルスレッド性のためにブラウザがフリーズしないという質問に答えるには、setTimeout(またはmootoolsのFunction.delay)を使って、ブラウザの解釈のためにタイマーを0または10msに設定してコードを延期します。 。また、関数の結果を渡すことができる場合には、コールバックをexecに渡すこともできます(ajaxと思ってください)。

+0

ご協力いただきありがとうございます。私は 'each'ループを見て、最適化しました。 - ' setStyles'は驚くほど遅いです!その関数の3回の呼び出しを1つに集約することで、多くの時間を節約できました。 – Oliver

+0

各プロパティを 'element 'にオーバーロードするため、処理速度が遅くなります。setStyle' - 追加される単一のCSSクラスと、それからスタイル/スタイル自体を変更するpos/heightなどを扱う方が良いです。追加したイベントはクラスに保存することもできますし、事前に委任していない場合は、すべてのループなどで新しい関数で作成することはできません。多くは得られる:) –

関連する問題