2007年2月16日(金)

« そういえばバレンタインデー | トップページ | なんとか出来ないかな?<JavaScriptでヒアドキュメント »

JavaScriptでsleepの実装を試みる

ぼくはまちちゃん!(Hatena) - デブサミ』というところで、
JavaScriptで、sleep
という話が出ているのを見かけ、そういえば1年程前のJavaScript触りはじめの頃に私も調べたなぁ……と懐かしく思い出されました……けれども、あれ、結局方法見付けたんだっけ?
確か、setTimeout()を駆使して実装している例を見つけた記憶があるのですが(当時はさっぱりわからなかった)、いま検索してもそれらしいのが見当たらない……。
で、それならと自分でも考えてみました。
すぐ思いつくのは、単純にループで時刻をポーリングする方法。
function    JSleep_NowaitLoop( sec ) {
    var startTime = (new Date()).getTime() ;
    var stopTime = startTime + Math.floor(1000*sec) ;
    for (;;) {
        var curTime = (new Date()).getTime() ;
        if ( stopTime <= curTime ) break ;
    }
}   //  end of JSleep_NowaitLoop()
でもこれだと、CPUに負荷がかかりすぎて、最近のブラウザだと警告ダイアログが出てしまいそう。
CPU負荷を軽くするため、なんとかイベント待ち状態を作れないかな、と思って、『そうそう、ダイアログ表示中は待ち状態になるや』と、IE で showModalDialog() を使ってモーダルダイアログを呼出し、それが指定時間で閉じるような実装をしてみるものの、
  1. ダイアログを非表示に出来ない(方法がわからない)。
  2. そもそもIEでしか動かない。
ということで、どうも今ひとつ。
で、最後に、ネットワークの伝送速度に着目。
要は、
  1. 適当なファイルをXMLHttpRequestで取得。
  2. XMLHttpRequestは同期モードで使用(Sjax……だっけ?)。
とすることで、ファイル取得時のリクエスト~レスポンスの間、CPUが待ち状態になることを利用しよう、と。
var JSleepDummyFile = './JSleep.js' ;

function    JSleep( sec ) {
    var startTime = (new Date()).getTime() ;
    var stopTime = startTime + Math.floor(1000*sec) ;
    for (;;) {
        var xmlHttpObj = null ;
        if ( typeof ActiveXObject != "undefined" ) {
            var msXml = [ 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP' ] ;
            for ( var ci=0; ci < msXml.length; ci++ ) {
                xmlHttpObj = new ActiveXObject( msXml[ci] ) ;
                if ( xmlHttpObj ) break ;
            }
        }
        else if ( typeof XMLHttpRequest != "undefined" ) {
            xmlHttpObj = new XMLHttpRequest() ;
        }
        if ( !xmlHttpObj ) break ;
        for (;;) {
            var curTime = (new Date()).getTime() ;
            if ( stopTime <= curTime ) break ;
            xmlHttpObj.open( 'GET', JSleepDummyFile + '?time=' + curTime, false ) ;
            xmlHttpObj.send( null ) ;
        }
        break ;
    }
}   //  end of JSleep()
こんな感じ。
伝送速度によって負荷が変わりそうだし誤差も大きいけれど、まぁ一応動作する(WinXP SP2上のIE6(Sleipnir)・Firefox2・Opera9で確認)……もっとも今はナローバンドなので、ブロードバンドでは試せないのだけれど。
動作サンプルはこちら

この記事をニフティクリップβに追加 この記事をはてなブックマークに追加 2007/02/16(金) 07:47 | | 記事の編集(管理者用)

風柳へひとこと(web拍手) 

おもいつき」カテゴリの記事

パソコン・インターネット」カテゴリの記事

覚書」カテゴリの記事

トラックバック

この記事のトラックバックURL:

記事との関連性が薄いものやSPAM等、管理人が不適切と見なしたトラックバックについては予告無く削除する場合が有ります。悪しからずご了承下さい。

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/161784/13928506

この記事へのトラックバック一覧です: JavaScriptでsleepの実装を試みる:

コメント

ネットワーク負荷が高まるので嫌な感じです。
あと、firefoxの実装の問題でもあるのですが、NowaitLoopもファイル取得もfirefox全体が止るのも嫌な感じです。

投稿 おーの | 2007/02/17 1:32:49


まぁ、もともと無理は承知なわけですが。
#もっとスマートな実装方法あれば教えてください。

| ネットワーク負荷
回線状態がよい環境ほどかかりますからね(苦笑)。
当方の環境(Bフレッツ100M)だと上下併せて800~1000パケット/10秒程度。~1Mbpsってところですかね。

| firefox全体が止る
IEもとまります。

XP上で試すと、
■IE6 SP2:全体停止。複数クライアント起動の場合、実行中のもの以外は動作。
■Firefox2.0.0.1:全体停止。複数クライアント起動の場合、実行中のもの以外も停止。
■Opera9.10:実行中もブラウザ操作可能。
#Firefox、意外といけてない……

ちなみに、XMLHttpRequestを同期モードで実行中には、setTimeoutによる割込もブロックされて(待たされて)しまいます<IE6とFirefox(Operaは未確認)。

投稿 風柳>おーの さん | 2007/02/17 4:54:10


firefoxって、ネットワークとかDNS要求とかが複数窓で完全には独立していないように見えますね。スレッド化が中途半端とか?

投稿 おーの | 2007/02/17 16:13:39


コメントを書く