狠狠撸

狠狠撸Share a Scribd company logo
Node.js で学ぶマルチスレッドプログラミング入門サイボウズ?ラボ / Shibuya.pm竹迫 良範 @TAKESAKO
2009/04/06Cybozu University2JavaScript
sleep のない言語 JavaScriptどうやって実現するか?function sleep(msec) { // CPU_100%  var t = (new Date()).getTime()-(-msec);   while ( (new Date()).getTime() < t ) {} }function sleep(msec) {   // LiveConnect  Packages.java.lang.Thread.sleep(msec); }
クロスブラウザで sleep を実現(無理矢理)function sleep(msec) {   try { // for IEwindow.showModalDialog(       "javascript:document.write('<script>"       + "window.setTimeout(function(){window.close()},"       +  msec + ");<"script>');");   } catch (e) {     try { // for Firefox, Opera with LiveConnectPackages.java.lang.Thread.sleep(msec);     } catch (e) {  // for Safari and others var limit = (new Date()).getTime() - (-msec);       while ((new Date()).getTime() < limit) {}     }   } }
1秒ごとに表示したい(よくある間違い)<script>function sleep(msec) {var t = (new Date()).getTime() - (-msec);  while ( (new Date()).getTime() < t );}function init() {var body = document.body;  sleep(1000);body.innerHTML += "<h1>Hello!</h1>";  sleep(1000);body.innerHTML += "<h2>Hello?</h2>";  sleep(1000);body.innerHTML += "<h3>Hello!?</h3>";};</script><body onload="init()"></body>
問題1:sleep している間 CPU_100% (><)
问题2:3秒后にまとめて表示される
setTimeoutで1秒ごとに表示する(正解)<script>setTimeout(function(){var body = document.body;body.innerHTML += "<h1>Hello!</h1>";setTimeout(function(){body.innerHTML += "<h2>Hello?</h2>";setTimeout(function(){body.innerHTML += "<h3>Hello!?</h3>";    }, 1000);  }, 1000);}, 1000);</script>
setTimeout.html – シングルスレッド+遅延
2009/04/06Cybozu University10				}, 1000);			}, 1000);		}, 1000);	}, 1000);}, 1000);
2009/04/06Cybozu University11				});			});		});	});});
yield
yield で1秒ごとに表示<!DOCTYPE html><title>Firefox2.0+ only</title><script type="application/javascript;version=1.7">(function(g){var f=arguments.callee;setTimeout( function(){f(g)},g.next())})((function(){  yield (1000);document.body.innerHTML += "<h1>Hello!</h1>";  yield (1000);document.body.innerHTML += "<h2>Hello?</h2>";  yield (1000);document.body.innerHTML += "<h3>Hello!?</h3>";})());</script>
yield.html– 疑似マルチタスク処理
やりたいこと = 細かく setTimeoutを呼ぶ// こんな風に書けたらいいなぁ(><)  for (var i = 0; i < 10000000; i++) {	//   すん	//  ごく	//   重たい	//    処理	//   ???setTimeout(次の行, 0); // ブラウザに処理を戻す	// でもループの中は繰り返したい  }  // 終了
JavaScript 1.7(Firefox 2.0+)
yield を含む関数は Generator になるfunction generator() {	for (var i = 1; i <= 1000; i++) {		document.title = i;		yield;	}}var g = generator(); // [object Generator]// まだ document.title は変更されない
Generator#nextで次の yield まで実行?戻るfunction generator() {	for (var i = 1; i <= 1000; i++) {		document.title = i;		yield;	}}var g = generator(); // [object Generator]g.next(); // document.title = 1;g.next(); // document.title = 2;g.next(); // document.title = 3;
uncaught exception: [object StopIteration]function generator() {	for (var i = 1; i <= 1000; i++) {		document.title = i;		yield;	}}var g = generator();for (var j = 1; j <= 998; j++) { g.next() }g.next(); // document.title = 999;g.next(); // document.title = 1000;g.next(); // Error: uncaught exception:           //       [object StopIteration]
Generator#closefunction generator() {	for (var i = 1; i <= 1000; i++) {		document.title = i;		yield;	}}var g = generator();for (var j = 1; j <= 998; j++) { g.next() }g.next(); // document.title = 999;g.next(); // document.title = 1000;g.close();
yield の引数が next() の戻り値になるfunction generator() {	for (var i = 1; i <= 1000; i++) {		document.title = i;		yield (i);	}}var g = generator();var r;r = g.next(); // r = 1;r = g.next(); // r = 2;r = g.next(); // r = 3;
next() の戻り値をチェックしてきちんと終了function generator() {	for (var i = 1; i <= 1000; i++) {document.title = i;		yield (i);	}	yield (-1); // 終了条件}var g = generator();var r;do { r = g.next() } while (r > 0); // 1...1000g.close();
巨大ループ中で setTimeout(f, 0) が呼べる!function generator() {	for (vari = 1; i <= 1000; i++) {document.title = i;		yield true;	}	yield false;}function driveGenerator(g) {    if (g.next()) { // ? yield true?var f = function(){ driveGenerator(g) };setTimeout(f, 0);	} else {g.close(); // ? yield false    }}driveGenerator( generator() );
yield + setTimeoutイディオムが完成(function(g){var f=arguments.callee;var t=g.next(); (t<0) ? g.close():setTimeout(function(){f(g)},t)})((function(){  for (vari = 0; i < 10000; i++) {document.title = i; // 重たい処理    yield (0); // ブラウザに一旦処理を戻す(setTimeout)  }  yield (-1); // 終了})());
yield すごい !
 でも… 贵颈谤别蹿辞虫でしか…
JavaScript1.7 の指定をしないと yield 動かない<script type="application/javascript;version=1.7">(function(g){var f=arguments.callee;var t=g.next(); (t<0) ? g.close():setTimeout(function(){f(g)},t)})((function(){  for (vari = 0; i < 10000; i++) {document.title = i; // 重たい処理    yield (0); // ブラウザに一旦処理を戻す(setTimeout)  }  yield (-1); // 終了})());</script>
28?
HTML5 関連Web Workers
HTML5 Web Workers APImain.htmlworker.js(1) var worker = new Worker(“worker.js”);ワーカースレッドの作成(2) worker.postMessage(”hello”);(3) onmessage = function(e) {var result = e.data + ”!”;(4)   postMessage(result);(5) worker.onmessage = function(e) {       // DOM 更新処理window.alert(e.data);
ワーカスレッドを呼び出す UIスレッドworker.html<title>HTML5 Web Workers</title><script>var worker = new Worker("worker.js");worker.onmessage = function(e){document.body.innerHTML += e.data;}worker.postMessage("hello");</script>
ワーカスレッドの定義(重たい処理を分離)worker.jsfunction sleep(msec) {var t = (new Date()).getTime() - (-msec);  while ( (new Date()).getTime() < t );}//↓ワーカ側でメッセージを受信したときの処理onmessage = function(e) {  sleep(1000);postMessage("<h1>" + e.data + "!</h1>");}
Web Workers のセキュリティUIスレッドワーカスレッドwindow.document.write(“hoge”)Workerスレッドからはwndowオブジェクトに触れない!CPU_100%でもブラウザ固まらない!
Firefox, Safari, Chrome で动作
2009/04/06Cybozu University35Node.js拡張できる?
2009/04/06Cybozu University36
2009/04/06Cybozu University37
v8-juice
jsthread.sourceforge.net
40?

More Related Content

Node.js - JavaScript Thread Programming