HTML、JavaScript のデバッグは、Google Chrome で開いて、右上ボタン、その他のツール、デベロッパー ツール、を使います (Console を表示)
(2022/01/28 19:20 更新: Show_CustomControl.html の class の宣言を、別ファイル (js) に分離)
(2022/01/28 23:00 更新: init(str, sub) に変更。load() から呼び出し。初期値を、DB を読み込んだ後など、に書ける)
(2022/02/04 18:45 更新:サーバー側のアドレスを拡張子なしに変更。RewriteRule を使う)
(2022/02/16 10:45 更新:フォルダ名やファイル名を変更)
Show_CustomControl.html
<html>
<head>
<meta charset='utf-8' />
<title>JavaScript Promise, resolve and then Sample</title>
<script>
function makeRequest() {
var select = document.getElementById('category');
var idx = select.selectedIndex;
var str = select.options[idx].value;
chbcapi.request({
'path': 'https://kamimatsu-db.com/Api/CustomControl/ChangeChild',
'method': 'POST',
'body': JSON.stringify( {'category': str} )
}).then(function(resp) {
writeResponse(resp.result);
});
}
function initChild(str, sub) {
var select = document.getElementById('category');
for (var i=0; i<select.options.length; i++) {
if (select.options[i].value == str) {
break;
}
}
select.selectedIndex = i;
chbcapi.request({
'path': 'https://kamimatsu-db.com/Api/CustomControl/ChangeChild',
'method': 'POST',
'body': JSON.stringify( {'category': str, 'subcategory': sub} )
}).then(function(resp) {
writeResponse(resp.result);
});
}
function writeResponse(response) {
console.log(response);
var select = document.getElementById('subcategory');
while(select.firstChild) {
select.removeChild(select.firstChild);
}
for (const elem of response) {
var option = document.createElement('option');
option.value = elem.value;
option.text = elem.text;
if (elem.selected) {
option.selected = true;
}
select.appendChild(option);
}
if (response.length > 0) {
select.disabled = false;
} else {
select.disabled = true;
var option = document.createElement('option');
option.value = " ";
option.text = " ";
option.selected = true;
select.appendChild(option);
}
}
</script>
<script async defer src="https://kamimatsu-db.com/Api/Js/ChbcApi.js">
</script>
</head>
<body>
<select id="category" name="category" size="1" onchange="makeRequest();" style="width: 170px;">
<option value="選んで下さい">選んで下さい</option>
<option value="先生">先生</option>
<option value="プログラマ">プログラマ</option>
<option value="デザイナー">デザイナー</option>
<option value="マッサージ">マッサージ</option>
<option value="カウンセル">カウンセル</option>
<option value="その他">その他(コメントへ記入)</option>
</select>
<select id="subcategory" name='subcategory' size="1" style='width:170px;' disabled>
<option value=" "> </option>
</select><br>
<script>
function load() {
initChild('プログラマ', 'COBOL');
}
window.onload=load;
</script>
</body>
</html>
ChbcApi.js
class ChbcApi {
request(data) {
console.log(data);
return new Promise(function(resolve) {
fetch(data.path, data)
.then(function(res) {
return( res.json() );
})
.then(function(json) {
console.log(json);
if ( Array.isArray(json) ) {
var resp = { result: json };
} else {
var resp = { result: JSON.parse(json) };
}
resolve(resp);
});
});
}
}
const chbcapi = new ChbcApi();
サーバーにアップロードする PHP ファイルです。POST 経由で、JSON のパラメータを受け取って、JSON で結果を返します
アドレス https://kamimatsu-db.com/Api/CustomControl/ChangeChild
パラメータ POST 又はアドレス
リクエスト本文 JSON
応答 JSON
ChangeChild.php
<?php
header("Content-Type: application/json; charset=utf-8");
header("Access-Control-Allow-Origin: *");
$json = file_get_contents('php://input');
$data = json_decode($json, true);
function opt($str, $sel)
{
return array( 'value' => $str, 'text' => $str, 'selected' => ($str == $sel) );
}
$res = array();
$sel = $data['subcategory'];
switch ($data['category']) {
case '先生':
$res[0] = opt("選んで下さい", $sel);
$res[1] = opt("英語", $sel);
$res[2] = opt("数学", $sel);
$res[3] = opt("物理", $sel);
$res[4] = opt("小学生", $sel);
$res[5] = opt("パソコン", $sel);
$res[6] = opt("その他(コメントへ記入)", $sel);
break;
case 'プログラマ':
$res[0] = opt("選んで下さい", $sel);
$res[1] = opt("C#", $sel);
$res[2] = opt("VB.NET", $sel);
$res[3] = opt("JAVA", $sel);
$res[4] = opt("Objective-C", $sel);
$res[5] = opt("C/C++", $sel);
$res[6] = opt("COBOL", $sel);
$res[7] = opt("Python", $sel);
$res[8] = opt("その他(コメントへ記入)", $sel);
break;
case 'マッサージ':
$res[0] = opt("選んで下さい", $sel);
$res[1] = opt("指圧", $sel);
$res[2] = opt("リラクゼーション", $sel);
$res[3] = opt("タイ古式", $sel);
$res[4] = opt("その他(コメントへ記入)", $sel);
break;
case 'カウンセル':
$res[0] = opt("選んで下さい", $sel);
$res[1] = opt("経営", $sel);
$res[2] = opt("恋愛", $sel);
$res[3] = opt("その他(コメントへ記入)", $sel);
break;
default:
break;
}
echo(json_encode($res));
?>
JavaScript の Promise、resolve、then の動作を確認したプログラムです
「function(resolve) {」は「(resolve) => {」に置き換えれます。「.then(function(resp) {」も同様に「.then((resp) => {」。request の data は渡されますが使っていません。resolve の resp が戻されて .then(function の resp (異なる名前でも良い) に渡されます
処理が失敗した時に異なる処理をしたい場合は、「function(resolve, reject) {」または「(resolve, reject) => {」 を作って、reject で error を戻して、「.catch(function(error) {」または「.catch((error) => {」で処理します
JavaScript では 「resp = { result: { name: "Ronaldo", team: "Juventus"} }」は resp.result や response.name のようにアクセスできます (ここで response = resp.result)。resp はオブジェクトと呼ばれています。PHP の配列とは扱いが異なりますね
var と const はスコープにだけ注意して適当に使っています。PHP の場合だと外で作った変数が function の内側に渡されません (必要ならば function の内側で global 宣言する)
request やその内側の fetch はマルチスレッドで動作しています。makeRequest(); の直後に <div id="info"> の内容を見ても、結果は更新されていません。続きの処理が必要ならば writeResponse() の中に書かなければなりません (または、return new Promise を書く)
※ promise.then の呼び出しは promise を返す
test.html
<html>
<head>
<meta charset='utf-8' />
<title>JavaScript Promise, resolve and then Sample</title>
<script>
var resource = {
"summary": "Appointment",
"location": "Somewhere",
"start": {
"dateTime": "2022-01-16T10:00:00.000-07:00"
},
"end": {
"dateTime": "2022-01-16T10:25:00.000-07:00"
},
"visibility": "public"
};
function makeRequest() {
chbcapi.request({
'path': '/calendar/v3/calendars/primary/events',
'method': 'POST',
'body': resource
}).then(function(resp) {
writeResponse(resp.result);
});
}
function writeResponse(response) {
console.log(response);
var divinfo = document.getElementById('info');
divinfo.append('name: ' + response.name + ', team: ' + response.team);
}
class ChbcApi {
request(data) {
console.log(data);
return new Promise(function(resolve) {
const resp = { result: { name: "Ronaldo", team: "Juventus"} };
resolve(resp);
});
}
}
const chbcapi = new ChbcApi();
</script>
</head>
<body>
<button id="rest" onclick="makeRequest();">Make Request</button>
<div id="info"></div>
</body>
</html>
簡単な fetch の例です。return や resolve を書かなければ、値を返さず、処理のみ行います (2番目の then)。fetch のマニュアルはこちら
<script>
fetch('https://ipinfo.io?callback')
.then(function(res) {
return( res.json() );
})
.then(function(json) {
console.log(json.ip);
var addr = document.getElementById("addr");
addr.innerHTML = json.ip;
});
</script>
<span id="addr"></span><br>
Promise 有りと Promise 無しを比較した例です。Promise 無しは先に "by initChild" が表示されて、3秒後に "by setTimeout" が表示されます。Promise 有りは両方ほぼ同時に表示されます
<html>
<head>
<meta charset='utf-8' />
<title>JavaScript Promise, resolve and then Sample</title>
<script>
function makeRequest() {
return new Promise(function(resolve) {
setTimeout(function() {
console.log("by setTimeout");
var divinfo = document.getElementById('info');
divinfo.append("by setTimeout");
resolve();
}, 3000);
});
}
function initChild() {
console.log("by initChild");
var divdata = document.getElementById('data');
divdata.append("by initChild");
}
function load() {
makeRequest()
.then(function() {
initChild();
});
}
window.onload=load;
</script>
</head>
<body>
<div id="info"></div>
<div id="data"></div>
</body>
</html>
以上、