document.getElementById("open").onclick = function(evt) と、ws.onopen = function(evt) の違いが、ようやく分かってきた件

document.getElementById("open").onclick = function(evt) と、ws.onopen = function(evt) が、混乱して、上手く動かなかったけど、ようやく分かりました(ような気ががしています)。

■document.getElementById("open").onclick = function(evt) { 処理内容}は、
"open"ボタンを押した時に行う処理を行い、
■ws.onopen = function(evt){処理内容}は、
websocketのopenのイベントが飛んできた時に行う

つまり、"ボタン"と"websocket"という、全く別物を取り扱っている、ということに、やっと気がつきました ―― 同じ"open"という言葉を使うので、混同していました。

なので、

ws.close()処理は、当然に、document.getElementById("open").onclick = function(evt) { 処理内容} の中で実施しなけばなりません。

ws.onopen = function(evt){処理内容}は、すでにwebsocketのclose処理が行われた後の処理を記載するので、ここでws.close()を記載したら、変なことになります(二重にwebsocketのclose処理をすることになる)


 

それと、位置情報をコールバックで取得する関数を、
const successCallback = (position) => { 処理内容 }

エラーイベントを検知する関数を、
const errorCallback = (err) => { 処理内容 }
と記載した場合、

このコールバックを登録する関数は、
watchPositionID = navigator.geolocation.watchPosition(successCallback, errorCallback, options);
であり、

このコールバックを停止する関数は、navigator.geolocation.clearWatch(watchPositionID);

となります。

という訳で、server26.goの"smartphoneTemplate"で登録している、htmlファイル(javascriptを含む)の部分だけ切り出したものを記載しておきます。

var smartphoneTemplate = template.Must(template.New("").Parse(`
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<script> 

let watchPositionID;  // グローバル変数として出しておく
let ws; // グローバル変数として出しておく

window.onload = () => {
	// これは、Web起動時に最初に読まれる部分であるが、今回、これらの関数は、全部
	// 	document.getElementById("open").onclick = function(evt) {  // openボタンを押した時 
	// 中に放り込んだ。 openボタンを押した後に起動するようにする為である

	// navigator.geolocation.watchPositionについては次のURLにかかれています。
	// https://developer.mozilla.org/ja/docs/Web/API/Geolocation/watchPosition

	// これが位置情報コールバックの起動コマンド
	//watchPositionID = navigator.geolocation.watchPosition(successCallback, errorCallback, options);

	// ここで(もう)webソケットを開く
	//ws = new WebSocket("{{.}}");

};

// ブラウザーを閉じる前に位置の監視を止めます
window.onbeforeunload = () => {
	// こちらの内容も
	// document.getElementById("close").onclick = function(evt) { // closeボタンを押した時
	// の中に放り込んだ  closeボタンを押した時に起動するようにする為である	

	// これが位置情報コールバック停止のコマンド	
	//navigator.geolocation.clearWatch(watchPositionID);
	
	//ws.close();
}


// 引数にはミリ秒を指定。(例:5秒の場合は5000)
function sleep(a){
	  var dt1 = new Date().getTime();
	  var dt2 = new Date().getTime();
	  while (dt2 < dt1 + a){
		dt2 = new Date().getTime();
	}
	  return;
}

// 以下の3つはグローバル変数として取り扱う
var personal_id =0;  
var lat;
var lng;  

//var ws;

// 位置情報を構造体として格納する為のファンクション(jsでは、こういう風に使うらしい)
function obj(id, lat, lng){
	this.id = id;
	this.lat = lat;
	this.lng = lng;
}

// 乱数生成装置 (minとmaxの間の乱数を作る)
function random(min, max){
	return  Math.random()*(max-min) + min;
}


window.addEventListener("load", function(evt) {
	// メッセージ表示部
    var output = document.getElementById("output");
    var input = document.getElementById("input");

    var print = function(message) {
        var d = document.createElement("div");
        d.textContent = message;
        output.appendChild(d);
	};

	///// 起動時のボタン設定(アクティブにしたり非アクティブにしたりする)
	// disabled属性を削除
	document.getElementById("open").removeAttribute("disabled");
	document.getElementById("open").style.color = "black";

	// disabled属性を設定 (closeボタンを非活性化)
	document.getElementById("close").setAttribute("disabled", true);
	document.getElementById("close").style.color = "White";			

	document.getElementById("open").onclick = function(evt) {  // openボタンを押した時
		console.log("document.getElementById open");

		// disabled属性を設定 (openボタンを非活性化)
		document.getElementById("open").setAttribute("disabled", true);
		document.getElementById("open").style.color = "White";		

		// disabled属性を削除(closeボタンを非活性化)
		document.getElementById("close").removeAttribute("disabled");
		document.getElementById("close").style.color = "black";	

        //if (ws) {
        //    return false;
        //}
	

		// ここでコールバック関数を起動
		watchPositionID = navigator.geolocation.watchPosition(successCallback, errorCallback, options);
		// websocket オープン
		ws = new WebSocket("{{.}}");
		// 最初はidを0にする
		personal_id = 0;   
			
		ws.onopen = function(evt) {  // 通信openイベントを検知した時(通信がopen状態になった後)
			print("OPEN");
		
			var send_obj = new obj(0, lat, lng);  // 最初はpersonal_idを"0"としてエントリ
	
			console.log("open:send_obj");	
			console.log(send_obj.id);	
			console.log(send_obj.lat);
			console.log(send_obj.lng);		
	
			var json_obj = JSON.stringify(send_obj);
			ws.send(json_obj);

		}

		ws.onclose = function(evt) {  // 通信closeイベント(×ボタン)を検知した時 (通信がclose状態になった後)
			print("onclose:CLOSE");
            ws = null;
        }

		ws.onmessage = function(evt) {  // 通信メッセージを受信した時(受信した後)
			print("RESPONSE: " + evt.data);  // jsonメッセージの内容を表示
			// データをJSON形式に変更
			var obj = JSON.parse(evt.data);

			personal_id = obj.id; // IDの取得(何回も取る必要はないが)
			console.log("personal_id");			
			console.log(personal_id);
			
			if ((Math.abs(obj.lat) > 90.0) || (Math.abs(obj.lng) > 180.0)){ // 異常な座標が入った場合は、マーカーを消去する
				console.log("before ws.close()");
				ws.close();
				console.log("after ws.close()");
			}
		}
		
        ws.onerror = function(evt) { //  エラーイベントを検知した時(検知した後)
            print("ERROR: " + evt.data);
        }
        return false;
    };
	
	document.getElementById("close").onclick = function(evt) { // closeボタンを押した時
		console.log(" document.getElementById close");

		// disabled属性を削除
		document.getElementById("open").removeAttribute("disabled");
		document.getElementById("open").style.color = "black";

		// disabled属性を設定 (closeボタンを非活性化)
		document.getElementById("close").setAttribute("disabled", true);
		document.getElementById("close").style.color = "White";	

        if (!ws) {
            return false;
		}
		
		var send_obj = new obj(personal_id, 999.9, 999.9); //  意図的に異常な位置情報を入れて正常終了させる処理

		console.log("close:send_obj");
		console.log(send_obj.id);		
		console.log(send_obj.lat);
		console.log(send_obj.lng);		

		var json_obj = JSON.stringify(send_obj);
		ws.send(json_obj);

		ws.close();  // これはws.closeの方で実施すると変なことになる  closeが実施された後で、close()することになる

		navigator.geolocation.clearWatch(watchPositionID); //コールバック関数の停止?

		personal_id = 0;   // 最後もidを0にする		
	
        return false;
    };
});

// 位置情報の取得に成功した際のコールバック

const successCallback = (position) => {
	console.log("successCallback:position");

	lat = position.coords.latitude;
	lng = position.coords.longitude;

	console.log(personal_id);
	console.log(lat);
	console.log(lng);

	//コールバックが発生するタイミングでサーバに位置情報を送付する

	if (personal_id != 0){
		var send_obj = new obj(personal_id, lat, lng);  // 最初は"0"でエントリ

		console.log("open:send_obj");	
		console.log(send_obj.id);	
		console.log(send_obj.lat);
		console.log(send_obj.lng);		

		var json_obj = JSON.stringify(send_obj);
		ws.send(json_obj);
	}

	// sleep(1000); // 1秒待つ	

}

// 位置情報の取得に失敗した際のコールバック
const errorCallback = (err) => {
	console.log(err);
};

// 位置を監視する構成オプション
// オプションの内容は次のリンクに書かれています。
// https://developer.mozilla.org/ja/docs/Web/API/PositionOptions
const options = {
	enableHighAccuracy: true,
	//timeout: 5000,
	timeout: 500000,
	maximumAge: 0
};

</script>
</head>
<body>
<table>
<tr><td valign="top" width="50%">
<p>Click "Open" to create a connection to the server, 
"Send" to send a message to the server and "Close" to close the connection. 
You can change the message and send multiple times.
<p>
<form>
<button id="open">Open</button>
<!-- <p><input id="input" type="text" value="Hello world!"> -->
<!-- <button id="send">Send</button> -->
<button id="close">Close</button>
</form>
</td><td valign="top" width="50%">
<div id="output"></div>
</td></tr></table>
</body>
</html>
`))

 


 

2020/10,江端さんの技術メモ

Posted by ebata