2011-07-26 19 views
40

これはばかげているようですが、サーバー側の要求を伴わないjQueryを使用して非同期関数呼び出しを行う方法を見つけることができません。私は、多くのDOM要素を反復処理する遅い関数を持っています。この関数が実行されている間、ブラウザーをフリーズしないようにします。私は、スロー関数が呼び出される前に小さなインジケータを表示したいと思います。スロー関数が返ってきたら、そのインジケータを隠したいと思います。私は、次があります。 jQuery非同期関数呼び出し、AJAX要求なし

$('form#filter', parentNode).submit(function() { 
    var form = $(this); 
    indicator.show(); 
    var textField = $('input#query', form); 
    var query = jQuery.trim(textField.val()); 
    var re = new RegExp(query, "i"); 
    slowFunctionCall(); // want this to happen asynchronously; all client-side 
    indicator.hide(); 
    return false; 
}); 

は現在、私は、フォームを送信し、インジケータが表示されていない、ブラウザがフリーズし、その後 slowFunctionCallを終了します。

編集

:ブラウザを凍結しないも

var indicator = $('#tagFilter_loading', parentNode); 
indicator.hide(); 
var spans = $('div#filterResults span', parentNode); 
var textField = $('input#query', parentNode); 
var timer = undefined, processor = undefined; 
var i=0, limit=spans.length, busy=false; 
var filterTags = function() { 
    i = 0; 
    if (processor) { 
    clearInterval(processor); 
    } 
    indicator.show(); 
    processor = setInterval(function() { 
    if (!busy) { 
     busy = true; 
     var query = jQuery.trim(textField.val()).toLowerCase(); 
     var span = $(spans[i]); 
     if ('' == query) { 
     span.show(); 
     } else { 
     var tagName = span.attr('rel').toLowerCase(); 
     if (tagName.indexOf(query) == -1) { 
      span.hide(); 
     } 
     } 
     if (++i >= limit) { 
     clearInterval(processor); 
     indicator.hide(); 
     } 
     busy = false; 
    } 
    }, 1); 
}; 
textField.keyup(function() { 
    if (timer) { 
    clearTimeout(timer); 
    } 
    /* Only start filtering after the user has finished typing */ 
    timer = setTimeout(filterTags, 2000); 
}); 
textField.blur(filterTags); 

このショーやインジケータを隠し、:は、私は、次の解決策を得るために、特に、Sitepoint linkVivin's answerを使用しました。 DOM要素が動作しているときに隠されているのを見ることができます。これが私の目的です。

+0

私はすべてのJSが1つのスレッドで動作すると思います。したがって、非同期に関数を実行することはできません。しかし、私はこれについて間違っているかもしれません:) – PeeHaa

+1

あなたの機能を減速させているDOM要素にどのようにアクセスしているかによって、この部分をスピードアップすることができます。クラスや属性フィルタ(遅い)を使ってJQueryで要素にアクセスしていますか?関数は2回以上実行されていますが、あなたがインタラクトしている要素/ IDをキャッシュする方法はありますか?影響を受けるすべての要素が使用するCSSクラスを変更して、同じDOMアップデートを実行できますか? – tomfumb

答えて

30

JavaScriptは1つのスレッドで実行されるため、機能が遅い場合はになります。は他のすべてをブロックします。あなたが望むもののいくつかの操作を行いますが、それらは広く(私は、彼らがIE10になると思う)IEでサポートをサポートされていないことを心に留めておくだろう

UPDATE

一部のWebワーカー上のリソース:

はここでウェブの労働者なしでマルチスレッドを実現するには、いくつかのリソースです。それは、これが「真」マルチスレッドではないことに注意することが重要です。

+0

まあ、これについてのチュートリアルを見つけることができないのは不思議ではありません...ありがとう。 –

+0

あなたは過去に正しいはずでしたが、現在は一部のブラウザがWebワーカーをサポートしています。 – nwellcome

+1

@nwellcome私はそれについても言及しましたが、広くサポートされていないという事実のために実行可能な選択肢ではありません。私は最終的に彼らが広く支持されることを願っています。それはそれが大いに役立つからです。 –

6

私は行っていたタイムアウトを見ることを提案するが、悲しいことだ。 John Resig(jQuery)のこの記事は、JavaScriptがどのようにシングルスレッドを処理するかについて少し説明しています。 http://ejohn.org/blog/how-javascript-timers-work/

This articleまた、「JavaScriptで関数を非同期に実行するときに覚えておくべきことは、関数呼び出しが完了するまで、ページ内の他のすべてのJavaScriptの実行が停止することです。あまりにも多くのものを同時に非同期的に呼び出そうとすると、実際のパフォーマンスの問題が発生します。長時間実行されている関数は、実際にユーザーのブラウザを「ロック」します。同じことは、同期機能があまりにも呼び出すために真実である。」

言ったことすべて、それはあなたが小さなチャンクにやっているものは何でもループ破り、setTimeoutメソッドを使用して自分自身を呼び出すあなたは、非同期機能をシミュレートすることができ可能です()。

例えば

この機能:

// Sync 
(function() { 
    for(var x = 0; x < 100000; ++x) {console.log(x)} 
})() 

// ASync 
var x = 0; 
setTimeout(function() { 
    console.log(x++); 
    if(x < 100000) setTimeout(arguments.callee, 1); 
} ,1) 
+0

arguments.callee(ES5以降厳密なモードでは使用できません)を使用しない場合は、コールバック関数に名前を付け、次の呼び出しでその名前を使用できます。たとえば、 var x = 0; setTimeout(function rec(){ console.log(x ++); if(x <100000)setTimeout(rec、1); } 1) – danpop

5

あなたはweb workers!

編集したい場合があります:多くの人が「そのことはできない」にジャンプどのように私は驚いているので、私は詳しく述べる。 WebワーカーはHTML 5 specの一部です。 UIをブロックすることなく、スクリプトをバックグラウンドで実行するためのスレッドを生成することができます。それらは外部のjsファイルでなければならず、

var worker = new Worker('my_task.js'); 

によって呼び出され、イベント経由で通信されます。

+0

あるかもしれません。そのページには「通常どおり、バックグラウンドスレッド(ワーカーを含む)はDOMを操作できません」と記載されています。 –

+0

Goooodポイントでは、ワーカーは 'window'、' document'または 'parent'にアクセスできないため、DOM操作はありません。 – nwellcome

+0

@nwellcome、それは可能ではありません*私はWeb Workersの可能性について非常に興奮しています。問題は、それらが広くサポートされていないことです(まだ)。 –

関連する問題