Web JavaScript

Web JavaScriptは WebクライアントサイドのDOM標準APIにおいて、JavaScript実行環境OgO上で 使えるオブジェクト、クラスと関数を説明します。


window オブジェクト ...

windowオブジェクトは global と同じオブジェクトです。したがって、windowオブジェクトのプロパティと関数は「.」で指定しないで呼び出せます。

例えば
     function fun() { alert("ok"); }
     setTimeout(fun, 1000);  // 1秒後に fun関数を実行する。
 
window : プロパティ・関数・・・リスト
clearInterval関数 setInterval関数で設定された繰り返し動作をキャンセルします。
clearTimeout関数 setTimeout関数で設定された遅延を解除します。
setImmediate関数 イベントループ中に遅延して、関数を実行します。
setInterval関数 一定の遅延間隔を置いて関数を繰り返し呼び出します。
setTimeout関数 指定された遅延の後に、関数を実行します。

clearInterval 関数window...

setInterval関数で設定された繰り返し動作をキャンセルします。

clearInterval( intervalID )

引数
intervalID : Integer
キャンセルする繰り返し動作の識別子。この ID は setInterval() の戻り値です。
参照
setInterval関数, clearTimeout関数

clearTimeout 関数window...

setTimeout関数で設定された繰り返し動作をキャンセルします。

clearTimeout( timeoutID )

引数
timeoutID : Integer
timeoutID は、解除したいタイマの ID です。ID は、setTimeout() の戻り値です。
参照
setTimeout関数, clearInterval関数

setImmediate 関数window...

イベントループ中に遅延して、関数を実行します。setTimeout(func,0)と同じ。

setImmediate( func )

引数
func : Function
遅延して呼び出される関数です。
参照
setTimeout関数

setInterval 関数window...

一定の遅延間隔を置いて関数を繰り返し呼び出します。

setInterval( func, delay ) : Integer

引数
func : Function
繰り返し呼びたい関数です。
delat : Integer
funcを呼び出す前に待つべきミリ秒数(1/1000 秒) です。
返値
    繰り返し呼出タイマーを識別する番号(識別子)を返します。
    この繰り返しを中止するには、この識別子を引数にしてclearInterval関数を呼び出します。
  
// 1秒毎に関数を5回呼び出す。
var cnt = 0;
var timerID;

function func() {
  cnt++;
  print(cnt + "回");
  if (cnt==5) clearInterval(timerID);
}

timerID = setInterval(func, 1000);

// 別バ-ジョン
var timerID;

function makefunc() {
  var cnt = 0;

  return function() {
    cnt++;
    print(cnt + "回");
    if (cnt==5) clearInterval(timerID);
  };
}

timerID = setInterval(makefunc(), 1000);
参照
clearInterval関数, setTimeout関数

setTimeout 関数window...

指定された遅延の後に、関数を実行します。

setTimeout( func, delay ) : Integer

引数
func : Function
delay ミリ秒後に実行したい関数です。
delat : Integer
関数呼び出しを遅延させるミリ秒(1/1000 秒)です。
返値
    指定時間後に呼出すタイマーを識別する番号(識別子)を返します。
    遅延呼出を中止するには、この識別子を引数にしてclearTimeout関数を呼び出します。
  
// 1秒毎に関数を5回呼び出す。
var cnt = 0;
var timerID;

function func() {
  cnt++;
  print(cnt + "回");
  if (cnt!=5) timerID = setTimeout(func, 1000);
}

timerID = setTimeout(func, 1000);
参照
clearTimeout関数, setInterval関数, setImmediate関数

console オブジェクト ...

標準出力と標準エラーに出力するためのものです。 ほとんどのブラウザで提供されているコンソールオブジェクトと同様ですが、 出力は標準出力か標準エラー出力に送られます。

ただし、OgO実行環境では デフォルト設定なら標準出力と標準エラーは OgOエディターに出力されます。


console : プロパティ・関数・・・リスト
log関数 標準出力へプリントします。
error関数 標準エラー出力にプリントします。

log 関数console...

標準出力へプリントします。

log( format, [data...] )

引数
format
C言語 printf関数と同じフォーマット文字列を指定します。
%変換子で data引数を変換してプリントします。
・%s --- 文字列
・%d --- 数値 (整数と浮動小数点数の両方)
・%f --- 浮動小数点数
・%i --- 整数
・%% --- %
data
%変換子に対応した値。
対応がなければ、文字列に変換してプリントします。
var count = 1;
//・・・
console.log('count: %d', count);
  
参照
console.error関数

error 関数console...

標準エラー出力にプリントします。

error( format, [data...] )

引数
format
C言語 printf関数と同じフォーマット文字列を指定します。
%変換子で data引数を変換してプリントします。
・%s --- 文字列
・%d --- 数値 (整数と浮動小数点数の両方)
・%f --- 浮動小数点数
・%i --- 整数
・%% --- %
data
%変換子に対応した値。
対応がなければ、文字列に変換してプリントします。
var count = 1;
//・・・
console.error('error! at count: %d', count);
  
参照
console.log関数

Worker クラス ... deprecated

警告! Worker クラスは近い将来、使用できなくなる可能性があります。

Workerは、messageデータ交換で並列処理(する方法)を提供します。

Workerは親子関係を持ちます。Workerオブジェクトをcreateする側を parent Worker、createされる側を child Workerと呼びます。

parent Workerと child Workerは並列動作し、お互いにmessageデータ交換して処理を共同作業できます。postMessage関数でmessageデータを送り、onmessage関数でmessageデータを受け取ります。messageデータは非同期で送られます。

child Workerは複数createでき、さらに (A) child Workerから (B) その子供child Workerが createできます。(A)は(B)の parent Workerでもあります。

以下は sample.jsプログラムとjob1.js, job2.jsプログラムが並列に実行されます。
・sample.js parent Worker メインプログラム
var worker1 = new Worker("job1.js");
worker1.onmessage = function (event) {
  var msg = event.data;
  print("1から" + msg.N + "までの素数の数は、" +
          msg.ans + "個です");
};

var worker2 = new Worker("job2.js");
worker2.onmessage = function (event) {
  var msg = event.data;
  print( "円周率 πの近似値 ≒ " + msg.ans + 
       " (試行回数=" + msg.N + ")" );
};

worker1.postMessage(1000000);
worker2.postMessage(1000000);

・job1.js child Worker 素数を数える
function primep( plist, i )
{
  var j;
  for (var iter=0, N=plist.length; iter<N; iter++) {
    j = plist[iter];
    if (j*j > i) return true;
    if (i%j==0) return false;
  }
}

function onmessage( event )
{
  var n = event.data;
  
  var plist = [];
  
  plist.push(2);
  plist.push(3);
  for (var j=5, r=3; j<=n; j+=2, r++) {
    if (primep(plist,j)) plist.push(j);
  }
  
  postMessage( {N:n, ans:plist.length} );
}

・job2.js child Worker モンテカルロ法でπを計算
function onmessage( event )
{
  var n = event.data;
  var hit = 0;
  
  for (var i=0; i<n; i++) {
    var x = Math.random(), y = Math.random();
    if ( x*x + y*y < 1 )
      hit++;
  }
  
  postMessage( {N : n, ans : 4*hit/n} );
}

・sample.js 実行結果
円周率 πの近似値 ≒ 3.143336 (試行回数=1000000)
1から1000000までの素数の数は、78498個です
  
Worker間の変数は共有できません!
Worker内で使われる変数はWorker間でお互いに独立して干渉しない仕組みになっています。
PostMessage関数で送って onmessage関数で データ値を受け取る以外に 共有する方法はありません。
並列処理においてこの制限は不便なであるように思えますが、データの同期で起こる データ整合性の喪失デッドロックなど深刻な問題に悩まずに安全かつ強固なプログラムが作成できる利点があります。

以下はエラーのある並列プログラムの例です。
例 エラーとなる並列処理
parent Worker メインプログラム
var worker = new Worker("job.js");
worker.onmessage = function (event) {
  print("1から" + N + "までの素数の数は、" +
          ans + "個です");    // ==> ReferenceError: N is not defined
};

worker.postMessage(1000000);

・job.js child Worker 素数を数える
var N, ans; // 「この2つの変数を parent Workerと共有する」考えで以下をスクリプトしている。

function primep( plist, i )
{
  var j;
  for (var iter=0, n=plist.length; iter<n; iter++) {
    j = plist[iter];
    if (j*j > i) return true;
    if (i%j==0) return false;
  }
}

function onmessage( event )
{
  var n = event.data;
  
  var plist = [];
  
  plist.push(2);
  plist.push(3);
  for (var j=5, r=3; j<=n; j+=2, r++) {
    if (primep(plist,j)) plist.push(j);
  }
  
  N = n;
  ans = plist.length;
  PostMessage(ans);
}
  

Worker : プロパティ・関数・・・リスト
Workerコンストラクター Workerオブジェクトを作成
onerror関数 Workerタスクで起きたエラーを受け取る関数
onmessage関数 postMessage関数で送られたイベントメッセージを受け取る関数
postMessage関数 イベントメッセージを送る関数
terminate関数 Workerオブジェクトを終了させる関数

Worker コンストラクター Worker...

Workerオブジェクトを作成

new Worker( filename ) : Worker
以下は非標準
new Worker( func ) : Worker
new Worker( scriptcode ) : Worker
new Worker( threadname, filename ) : Worker
new Worker( threadname, func ) : Worker
new Worker( threadname, scriptcode ) : Worker

引数
filename : String
JavaScriptプログラムのファイル名。
func : Function
引数を持たない関数。
scriptcode : String
JavaScriptコード。
改行を含む文字列はJavaScriptコードと評価します。
threadname : String
スレッド名。これが指定された場合、独立したスレッド内でWorkerが動作します。
返値
Workerオブジェクトが作成される。
解説
Workerオブジェクトが作成される(child Worker)と同時に、引数に渡されたプログラム(filename,scriptcode)あるいは関数(func)は現在のJavaScriptコンテキスト(parent Worker)と並列に実行され、child Workerはonmessage関数にmessageが送られてくるまでready状態になります。したがって、filename, scriptcode, func内には必ずonmessage関数がなけれいけません。
また、Workerオブジェクトを作成する側(parent Worker)もchild WorkerのpostMessage関数で送られたmessageを受け取る関数をWorkerオブジェクトのonmessageメソッド関数を備えている必要があります。もし、onmessage関数がなければ送られたmessageは無視されます。
var worker = new Worker(function(){
    var onmessage = function ( event ) {
        var n = event.data;
        var S = 0;
        for (var i=1; i<=n; i++) {
            S += i;
        }
        postMessage(S);
     }
});

worker.onmessage = function (event) {
  var S = event.data;
  print("合計は " + S + "です。");
};

worker.postMessage(10);
worker.postMessage(100);

/* 実行結果
合計は 55です。
合計は 5050です。
*/

onerror 関数 Worker...

Workerタスクで起きたエラーを受け取る関数

worker.onerror = function (error) {
  ...// 処理
};

引数
error : Object
error={ message : "エラー内容文字列", filename : "ファイル名", lineno : エラー行番号 }
返値
値は返しません。
var worker = new Worker(function(){
    var onmessage = function ( event ) {
        throw new Error("error N="+event.data);
     }
});

worker.onmessage = function (event) {
  var S = event.data;
  print("合計は " + S + "です。");
};

worker.onerror = function (event) {
  print(event.message);
};

worker.postMessage(10);
worker.postMessage(100);

/* 実行結果
error N=10
error N=100
*/
参照
onmessage関数

onmessage 関数 Worker...

postMessage関数で送られたイベントメッセージを受け取る関数

worker.onmessage = function (event) {
  //child Worker から送られたイベントメッセージを受け取る
  ...// 処理
};

var onmessage = function (event) {
  //parent Worker から送られたイベントメッセージを受け取る
  ...// 処理
};

引数
event : Object
event={ data : postMessage関数から送られたデータ }
返値
値は返しません。
var worker = new Worker(function(){
    var onmessage = function ( event ) {
        var n = event.data;
        var S = 0;
        for (var i=1; i<=n; i++) {
            S += i;
        }
        postMessage( { N:n, S : S } );
     }
});

worker.onmessage = function (event) {
  var response = event.data;
  print("1~" + response.N + "の合計は " + response.S + "です。");
};

worker.postMessage(10);
worker.postMessage(100);

/* 実行結果
1~10の合計は 55です。
1~100の合計は 5050です。
*/
参照
postMessage関数, onerror関数

postMessage 関数 Worker...

イベントメッセージを送る関数

worker.postMessage(data) : void child Worker へイベントメッセージを送る
postMessage(data) : void parent Worker へイベントメッセージを送る

引数
data : Any
イベントメッセージとして送られるデータ
onmmesage(event)関数ではその値を event.data でアクセスできます。
参照
onmessage関数

terminate 関数 Worker...

Workerオブジェクトを終了させる関数

worker.terminate() : void

解説
terminate関数を実行した時点で、postMessage関数で送った未処理のメッセージは強制終了し、Workerはkillされています。当然postMessage関数でメッセージを送っても受け付けません。
var worker = new Worker(function(){
  function primep( plist, i )
  {
    var j;
    for (var iter=0, N=plist.length; iter<N; iter++) {
      j = plist[iter];
      if (j*j > i) return true;
      if (i%j==0) return false;
    }
  }

  function onmessage( event )
  {
    var n = event.data;
    
    var plist = [];
    
    plist.push(2);
    plist.push(3);
    for (var j=5, r=3; j<=n; j+=2, r++) {
      if (primep(plist,j)) plist.push(j);
    }
    
    postMessage( {N:n, ans:plist.length} );
  }
});

var count = 0;
worker.onmessage = function (event) {
  var msg = event.data;
  print("1から" + msg.N + "までの素数の数は、" +
                    msg.ans + "個です");
  count++;
  if (count==5) {
      worker.terminate();
  }
};

for (var i=0; i<100; i++) {
  worker.postMessage(1000000);
}

/* 実行結果
1から1000000までの素数の数は、78498個です
1から1000000までの素数の数は、78498個です
1から1000000までの素数の数は、78498個です
1から1000000までの素数の数は、78498個です
1から1000000までの素数の数は、78498個です
*/