okinawa

IT勉強メモ

PHPの基本

特徴

HTMLの中に記述できる

<body>
<?php $i = 10 ?>
</body>

インポート

基本的にはrequire_onceでよさそう。

require('test.php');
require_once('test.php');
include('test.php');
include_once('test.php');

PHPファイルのインポート↓ https://it.becrazy.jp/article/php-import

変数

変数名の前に$をつける。

$i = 10;

定数

const $j = 20;

関数

function hoge(hikisuu) {
// 何か処理
return ~ ;
}

引数と戻り値には型指定ができる 引数:string 戻り値:int

function hoge(string hikisuu): int { 
// 何か処理 
return ~ ; 
}

配列

$hoge = array(1, 2, 3); //配列宣言
$hoge[0]; // 配列の取り出し

配列の末尾に要素追加

$hoge = array(1, 2, 3); //配列宣言
$hoge[] = 4; 

配列の上書き

$hoge = array(1, 2, 3); //配列宣言
$hoge[2] = 4; 

連想配列

Javaでいう所のMapみたいなの。

$array = array('apple'=>'りんご', 'peach'=>'もも', 'pear'=>'なし');

appleがキーでりんごが値。

取出し

$array[apple]; // りんご

条件文

if,for,whileはJavaと全部同じ。

foreach文

普通の配列

$hoge = array(1, 2, 3); //配列宣言
foreach($hoge as $num) {
    echo $num;
}

連想配列

$array = array('apple'=>'りんご', 'peach'=>'もも', 'pear'=>'なし');
foreach($hoge as $key => $num) { echo $num;}
foreach($hoge as $num) { echo $num;} //省略バージョン。結果は同じ。

文字列

文字列の結合

ドット「.」でつなぐ

"あういうえお"."かきくけこ";

シングルクォートとダブルクォートの違い

ダブルは変数が展開される  シングルは変数が展開されない

$data1 = "サポートサイト\t「{$title}」へ<br />"; 
$data2 = 'サポートサイト\t「{$title}」へ<br />'; 
print $data1; //サポートサイト 「サーバサイド技術の学び舎 - WINGS」へ
print $data2; //サポートサイト\t「{$title}」へ

var_dump

エラー出た時、変数の中身を見るのに重宝する。

$x = ['a','b','c']; 
var_dump($x);

日付

$today = new DateTime(); 
print($today->format('Y年 m月 d日 (D) G時 i分 s秒')); // 2021年 03月 29日 (Mon) 11時 11分 17秒

クラス

class SampleClass 
{ 
    public function publicFnction() 
    { 
        print('public呼び出し'); 
    } 
} 
$sample_class = new SampleClass();  // newでインスタンス化
$sample_class->publicFnction();// インスタンスメソッド呼び出し

例外処理

Javaと同じ

try { 

} catch (Exception $e) { 

} finally { 

}

DB連携

PDO(PHP Data Object)

DB抽象化レイヤのこと。 これのおかげでどのDBにも似たような記述で接続できる。 PHPに標準装備されている。

DB接続

function getDb() { 
  $dsn = 'mysql:dbname=selfphp; host=127.0.0.1; charset=utf8'; 
  $usr = 'root'; 
  $password = 'password'; 
  
  //DB接続
  $db = new PDO($dsn, $usr, $password); 

  // 例外処理を有効化
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  return $db;
  }

DB検索処理

function getDb() { 
  $dsn = 'mysql:dbname=selfphp; host=127.0.0.1; charset=utf8'; 
  $usr = 'root'; 
  $password = 'password'; 
   
  //DB接続 
  $db = new PDO($dsn, $usr, $password);  
  // 例外処理を有効化 
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
  return $db; 
  } 
try { 
  //上記DB接続のgetDbメソッドでDB接続 
  $db = getDb(); 
  // 例外処理を有効化 
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
  // 検索SQLプレースホルダで準備 
  $stt = $db->prepare("SELECT * FROM book WHERE title LIKE \'%?%\'"); 
  
  // 1個目の?のところにtitleが入る
  $stt->bindValue(1, $_POST['title']); 
  // SELECT命令を実行
  $stt->execute(); 

 //検索結果の取得 PDO::FETCH_ASSOCは連想配列で取得
  while($row = $stt->fetch(PDO::FETCH_ASSOC)) {
    $isbn = $row['isbn']
    $title = $row['title']
    $price = $row['price']
  }
  // 例外が発生したら、エラー表示 
} catch(PDOException $e) { 
  print "エラーメッセージ:{$e->getMessage()}"; 
} finally { 
  $stt = null; 
  $db = null; 
}

DB更新処理

function getDb() { 
  $dsn = 'mysql:dbname=selfphp; host=127.0.0.1; charset=utf8'; 
  $usr = 'root'; 
  $password = 'password'; 
   
  //DB接続 
  $db = new PDO($dsn, $usr, $password);  
  // 例外処理を有効化 
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
  return $db; 
  }
try { 
  //上記DB接続のgetDbメソッドでDB接続 
  $db = getDb(); 
  // 例外処理を有効化 
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
   
  // ドランザクションを開始 
  $db->beginTransaction(); 
  // 更新SQLプレースホルダで準備 
  $stt = $db->prepare('INSERT INTO book(isbn, title, price, publish, published) VALUES(:isbn, :title, :price, :publish, :published)'); 
  $stt->bindValue(':isbn', $_POST['isbn']); 
  $stt->bindValue(':title', $_POST['title']); 
  $stt->bindValue(':price', $_POST['price']); 
  $stt->bindValue(':publish', $_POST['publish']); 
  $stt->bindValue(':published', $_POST['published']); 
  // insert命令を実行 
  $stt->execute(); 
  // 全ての処理が完了したらトランザクションをコミット 
  $db->commit(); 
  // 例外発生したら、エラー表示&トランザクションをロールバック 
} catch(PDOException $e) { 
  $db->rollBack(); 
  print "エラーメッセージ:{$e->getMessage()}"; 
} finally { 
  $stt = null; 
  $db = null; 
}

HTML内での色々

phpタグ内でHTML文をつくる

echo or printするとHTML扱いになぜかなる。

<body>
<?php
for($i = 1; $i < 10; $i++) {
echo $i."
";
}
?>
</body>

phpタグ内でHTMLと変数を扱う

'{$変数}'

<?php
$i = abc
echo "<select name='{$i}'></select>";
?>

GET POSTをHTML内で受け取れる

$GET・$POST

//post送信
<form method="post" action="sent.php">
        <input type="text" name="name">
        <input type="submit" value="送信">
</form>
<body>
//post受け取り
<?php echo $_POST['name']; ?>
</body>

セキュリティ

XSS対策

基本的にGETやPOSTで受け取った値には、htmlspecialchars関数を使ってエスケープ処理をする。

例:XSS防止用のeメソッドを定義。

encode.php

<?php 
/** 
 * クロスサイトスクリプティング(XSS)防止用。 
 * ユーザー入力値をHTML表示する時に呼び出す。 
 * $str:エンコード対象の文字列 
 * #charset:エンコードタイプ 
 * ENT_QUOTES | ENT_HTML5:シングル/ダブルクォートを双方エスケープし、HTML5文書として処理。原則はこれ。 
 */  
function e(string $str, string $charset = "UTF-8"): string { 
  return htmlspecialchars($str, ENT_QUOTES | ENT_HTML5, $charset); 
} 

eメソッドを使う

<?php
require_once("./encode.php");

print (e($_GET['name']);
print e($_GET['password']);

セッションID盗聴対策

ログイン後に新しいセッションIDを生成する。

// 新しいセッションIDを生成。セッション情報は保持される。
session_regenerate_id();

IPA安全なウェブサイトの作り方のP17を参照↓ https://www.ipa.go.jp/security/vuln/websecurity.html

パスワードの暗号化・ハッシュ化

1、ハッシュの生成

$password = "1234";
$hash = password_hash($password, PASSWORD_DEFAULT); //ハッシュパスワードの生成

2、ハッシュとパスワードの照合

$password = "1234"; 
$hash = password_hash($password, PASSWORD_DEFAULT);

// password_verifyで照合
if(password_verify($password, $hash)){ 
        print "照合成功"
      }

全角カタカナでLIKE検索すると半角カタカナの濁点・半濁点がヒットしない問題

utf8_unicode_ci

utf8_unicode_ciを指定すると半角カナ、全角カナ、ひらがな、カタカナを区別せず、かなり広範囲にわたってマッチするようになる。

濁点・半濁点が付いていても無視する。

SELECT * FROM hoge WHERE bigName collate utf8_unicode_ci LIKE '%keyword%'

ただし、全角半角カタカナの濁点、半濁点付きのLIKE検索はマッチしない。

例:全角カタカナ「プ」「ゲ」でLIKE検索すると半角カタカナ「プ」「ゲ」がヒットしない。逆もダメ。

じゃあどうするの?

REPLACEで濁点半濁点を消す。

SELECT * FROM skill WHERE(REPLACE(REPLACE(bigName, '゙', ''), '゚', '') collate utf8_unicode_ci LIKE REPLACE(REPLACE(?0, '゙', ''), '゚', ''))

REPLACEで2回くくって濁点と半濁点を消している。

できればやりたくない。

ちなみにイコール検索なら大丈夫。

MySQLのCollation

MySQLのCollationは下記が無難かと。

  • utf8mb4_general_ci
  • utf8mb4_bin

は ぱ ば を区別してくれます。

参考

qiita.com

tmge.hatenablog.com

qiita.com

結論

DBに半角カタカナを登録するのやめよう!

どうしてもって言うなら半角全角カタカナを混在させるのやめよう!!!

すごいめんどくさかった!!!!!!

もしくはutf8mb4_general_ciかutf8mb4_binを使おう。

【JavaScript】非同期処理の基本

非同期処理のイメージ

処理スタート

→非同期処理もスタート、でも完了は後回し

→先に同期処理が完了

→非同期処理が終わった順に完了

必ず、同期処理が先に完了する!

非同期処理の大前提!

非同期処理を実装するには、非同期的な処理をする関数を使うこと。

例えば

  • setTimeout()
  • fs.readFile()
  • Promise()
  • async function()
  • XMLHttpRequest.onreadystatechange

などのこと。

ネットで調べるとコールバック関数=非同期みたいに見えてしまうが、全然そんなことはないので要注意。

誤解を恐れずに言えば、コールバック関数・Promise・async/awaitは非同期処理を同期処理にする時に使う。

非同期でバラバラに完了すると困るから同期処理にしちゃいましょうねーという感じ。

・参考

JavaScript中級者への道【4. 非同期関数】

https://qiita.com/matsuby/items/3dd9cfca8c7b0685e474

JavaScript中級者への道【5. コールバック関数】

https://qiita.com/matsuby/items/3f635943f25e520b7c20

JavaScriptの非同期処理を理解する その1 〜コールバック編〜

https://knowledge.sakura.ad.jp/24888/

非同期処理の書き方4つ

とりあえず書き方だけ。それぞれの詳しいことは後述。

・普通に書く これ非同期処理なんです。

なぜならsetTimeout関数が非同期で動く関数だから。

同時に3つのsetTimeoutが動き始める。

function before(string) {
  console.log(string);
}

function sample() {
  setTimeout(before, 3000, 1);
  setTimeout(before, 2000, 2);
  setTimeout(before, 1000, 3);
}
sample();

・コールバック関数

setTimeout(function one() {
  console.log(2000)
  setTimeout(function two(){
    console.log(4000)
    setTimeout(function three() {
      console.log(6000);
    }, 6000);
  },4000);
},2000);

・Promise

function async(param){
  return new Promise(function(resolve, reject) {
  setTimeout(function(){
    resolve(param);
  }, 2000);
});
}

async(2000)
  .then(function(param){
    console.log(param);
    return async(4000);
  })
  .then(function(param){
    console.log(param);
    return async(6000);
  })
  .then(function(param){
    console.log(param);
  })
  .catch(function(error){
    console.log(error);
  });
  
  function foo() {
  return new Promise((resolve, reject) => {
    setTimeout(function(){
    resolve('A');
    }, 5000);
  });
}

・async/await

function test() {
  // 非同期処理
  return new Promise(function(resolve, reject){
    resolve(); // 成功。thenが呼ばれる
    reject(); // 失敗。catchが呼ばれる
  });
}

async function test2() {
  // 非同期処理の呼び出し。同期的に上から順に終わってから次の処理へ行く。
  await test();
  await test();
  return '成功';
}

test2().then(function() {
  // 成功時の処理
})
 .catch(function() {
   // 失敗時の処理
 });

非同期処理の不思議な所

必ず同期処理が終わった後に、非同期処理が完了するみたいだぞ。 ただし、非同期処理も裏では動いていて、同期処理が終わった瞬間、すでに完了済みの非同期処理も完了する。(意味不明な日本語だけどそんな感じなんだよ。)  下記コードを動かしてみるとよくわかる。  「8秒後に8000ミリ秒経過しました!と1と2」が同時に表示→その2秒後に3が表示

// 非同期処理
function sample() {
  setTimeout(before, 1000, 1);
  setTimeout(before,2000, 2);
  setTimeout(before, 10000, 3);
}

// 同期処理
function sleep(wait) {
  var start = new Date();
  // 指定ミリ秒間だけループさせる
  while (new Date() - start < wait);
  console.log(`${wait}ミリ秒経過しました!`);
}

function before(string) {
  console.log(string);
}

sample();
sleep(8000);
--------------------
(出力結果)
8000ミリ秒経過しました! 
1 
2
3

なぜコールバック関数で非同期処理を書くのか?

処理に順番をつけたいから。

  • 例1(順番を付けない)

下記コードはundeifinedが表示される。

なぜなら、必ず同期処理が終わってから非同期処理が完了するから。

つまり、同期処理であるconsole.log(hoge)が終わってから

→非同期処理のsetTimeout(function() {  hoge = 'hoge';}, 0);が完了するから。

let hoge; 
// 0秒後にhogeに文字列を代入する 
setTimeout(function() { 
  hoge = 'hoge'; 
}, 0); 
console.log(hoge);  // => undefined

非同期処理にコールバック関数で順番を付ける

  • 順番付けない例 1秒後に1→2秒後に2→3秒後に3が表示。合計3秒。 全てのsetTimeoutがほぼ同時に開始する。
function sample() { 
  setTimeout(before, 1000, 1); 
  setTimeout(before,2000, 2); 
  setTimeout(before, 3000, 3); 
}
  • 順番を付けた例 コールバックをネストする。 1秒後に1→その2秒後に2→その3秒後に3が表示。合計6秒。
setTimeout(function one() {
  console.log(1)
  setTimeout(function two(){
    console.log(2)
    setTimeout(function three() {
      console.log(3);
    }, 3000);
  },2000);
},1000);

つまり非同期処理を非同期じゃなくしてる感じ。 1が終わってから2、終わってから3。

非同期処理の何がうれしいのか?

重たい処理を非同期で裏でやってもろて、同期処理は先に進めとく。

setTimeout(function one() {
  console.log(1)
  setTimeout(function two(){
    console.log(2)
    setTimeout(function three() {
      console.log(3);
    }, 3000);
  },2000);
},1000);
console.log(4) //ここだけ同期処理
-----------------------
4
1
2
3

コールバック関数の引数の値ってどこからとってきてるの?

https://qiita.com/matsuby/items/3f635943f25e520b7c20#%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%AA%E3%81%84%E3%81%A8%E6%84%9F%E3%81%98%E3%82%8B%E6%B0%97%E6%8C%81%E3%81%A1%E6%82%AA%E3%81%95

例 fs.readFile() err,dataの値はいったどこからやってくるのか・・・。

fs.readFile('/etc/passwd', function(err, data) {
  if (err) throw err;
  console.log(data);
});

答え:高階関数(呼び出し元の関数)がとってくる

// showHogeに呼び出される高階関数 
// ここで引数に値を代入
function call(callback){ 
  let string = 'コールバック関数の引数に入る値'; 
  let string2 = ':2個目'; 
  callback(string, string2); 
} 
//ここだけ見ると、引数stringに何が入っているか謎。 
function showHoge() { 
  call(function(string , string2){ 
    console.log(string+string2); 
  }); 
} 
showHoge();  // => コールバック関数の引数に入る値:2個目

Promise

・参考 JavaScriptの非同期処理を理解する その2 〜Promise編〜

https://knowledge.sakura.ad.jp/24890/

JavaScript Promise の基本的な使い方

http://javascript.keicode.com/lang/promise-basics.php

・基本的な書き方

const promise = new Promise(function(resolve, reject) {
    //ここに非同期の重い処理を書く
    resolve('成功'); // 非同期処理成功時の処理
        reject('失敗'); // 非同期処理失敗時の処理
}

Promise の状態は以下のいずれかとなります。

  • 待機pending: 初期状態。成功も失敗もしていません。
  • 満足fulfilled: 処理が成功して完了したことを意味します。
  • 拒絶rejected: 処理が失敗したことを意味します。

満足するとthen()が実行され 拒絶されるとcatch()が実行される。

function async(param){
  return new Promise(function(resolve, reject) {
  setTimeout(function(){
    param += 500;
    
    if(param >= 2000) {
      resolve(param);
    } else {
      reject('failed.')
    }
  }, 2000);
});
}

async(2000)
  .then(function(param){
    console.log(param);
    return async(4000);
  })
  .then(function(param){
    console.log(param);
    return async(6000);
  })
  .then(function(param){
    console.log(param);
  })
  .catch(function(error){
    console.log(error);
  });

・流れ Promise内の処理が実行

→処理の結果をparamに渡す

 →(満足)then内の処理が実行

 →(拒否)catch内の処理が実行

thenはその時って意味だから、async().then()はasync関数が完了したその時ってことだね。

・Promiseはコールバックの入れ子構造

resolve/rejectにも関数が入る。

Promise(function(resolve, reject)

Promise(コールバック関数1(コールバック関数1-1, コールバック関数1-2)という入れ子構造。

  • コールバック関数1にはthen/catchが入る
  • コールバック関数1-1にはthenの中のコールバック関数が入る。
  • コールバック関数1-2にはcatchの中のコールバック関数が入る。

Promiseの理解が深まるかもしれないちょっと不思議な奴

return foo(B)ではなく、return 'B';なとこごポイント。 これはプロミスは1回しか呼んでないので、returnの値がそのまま次のthenに入ってるんだと思う。

function foo() { 
  return new Promise((resolve, reject) => { 
    resolve('A') 
  }) 
} 
foo() 
  .then((value) => { 
    console.log(`1st: ${value}`) 
    return 'B' 
  }) 
  .then((value) => { 
    console.log(`2nd: ${value}`) 
    return 'C' 
  }) 
  .then((value) => { 
    console.log(`3rd: ${value}`) 
  }) 
  .catch((reason) => { 
    console.log('catch!') 
    console.log(reason) 
  }) 
// 1st: A 
// 2nd: B 
// 3rd: C

Promise のチェインニング https://javascript.keicode.com/lang/promise-basics.php#4

・疑問 thenのreturn値が次のthenの引数に入っている。 これはthenに限らず、普通のメソッドチェーンでもそういうものなの? たとえばJavaではこんな風に書くけど引数は普通に指定してるもんね。

String str1 = "abc123abc123"; 
boolean str2 = str1.replace("abc", "0").contains("0");
System.out.println(str2); // true

Promiseの理解が深まるかもしれないちょっと不思議な奴2

下記は一見すると、thenのどこかで3未満になったらFailedを返すように見える。 しかし、実はそうではない。 getNumberが呼ばれているのが最初の1回だけなのがポイント。 つまり、Promiseが呼ばれているのも最初の1回だけ。 だから、最初の1回だけ if (num >= 3) の判定をしている。 だから最初が3以上なら、その後3未満になってもrejectにならない。

function getNumber(num) {
    return new Promise(function(resolve, reject) {
        // numが3以上ならnumを返し、3未満なら"Falied!"のメッセージを返す
        if (num >= 3) {
            setTimeout(function() {
                resolve(num);
            }, 1000);
        } else {
            reject("Falied!");    
        }
    });  
}

// 今回は3を渡しているので、resolveから3が返ってくる
getNumber(3).then(function(result) {
    console.log(result);
    //numに3を加算して、getNumberに返している
    return result + 3;
}).then(function(result) {
    //上と同じ処理の繰り返し。これがチェイン
    console.log(result);
    return result - 6;
}).then(function(result) {
    // 最終結果として、numに6を加算した数を表示
    console.log(result);
})
  .catch(function(error){
    // 3未満の場合はrejectが呼び出され、"Falied!"のメッセージが表示される
    console.log(error);
  });
-----------
3
6
0

もし、上記を修正してthenの途中でもエラー判定をするなら。 return result +3; →return getNumber(result + 3); に変更する。

getNumber(3).then(function(result) {
    console.log(result);
    //変更箇所。getNumberを呼び出している。
    return getNumber(result + 3);
}).then(function(result) {
    console.log(result);
    //変更箇所。getNumberを呼び出している。ここでエラー。
    return getNumber(result - 6);
}).then(function(result) {
    console.log(result);
})
  .catch(function(error){
    // 3未満の場合はrejectが呼び出され、"Falied!"のメッセージが表示される
    console.log(error);
  });
--------------
3
6
Failed!

Prmiseの例外処理

・catch/finallyをつけられる。

function async(param){ 
  return new Promise(function(resolve, reject) { 
  setTimeout(function(){ 
    param += 500; 
     
    if(param >= 2000) { 
      resolve(param); 
    } else { 
      reject('failed.') 
    } 
  }, 2000); 
}); 
} 
async(2000) 
  .then(function(param){ 
    console.log(param); 
    return async(4000); 
  }) 
  .then(function(param){ 
    console.log(param); 
    return async(6000); 
  }) 
  .then(function(param){ 
    console.log(param); 
  }) 
  .catch(function(error){ 
    console.log(error); 
  })
  .finally(function() {
   console.log('ファイナリー');
 })

Promiseの関数

・参考 Primiseの静的メソッド https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise#static_methods

Promise.all 全てのPromiseがresolveする、または1つでもrejectするとPromiseが返ってくる。 戻り値は配列。

unction one(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    resolve(1000);
  }, 1000);
  });
}

function two(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    resolve(2000);
  }, 2000);
  });
}

function three(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    reject(3000);
  }, 3000);
  });
}

Promise.all([one(), two(), three()])
 .then(function(values){
   console.log(values);
 })
 .catch(function() {
   console.log('rejectだよ。');
 })
---------
1000, 2000, 3000

Promise.race Primise1つでもresolve/rejectするとPromiseを返す。

function one(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    reject(1000);
  }, 1000);
  });
}

function two(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    resolve(2000);
  }, 2000);
  });
}

function three(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    resolve(3000);
  }, 3000);
  });
}

const promises = [one(), two(), three()];

Promise.race([one(), two(), three()])
 .then(function(values){
     console.log(values);
 });
 .catch(function() {
   console.log('rejectだよ。');
 });
------------
rejectだよ。

Promise.any Promiseが1つでもresolveする、または全てrejectするとPromiseを返す。 まだ実験段階で、対応ブラウザ少ない。

function one(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    reject(1000);
  }, 1000);
  });
}

function two(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    resolve(2000);
  }, 2000);
  });
}

function three(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    resolve(3000);
  }, 3000);
  });
}

const promises = [one(), two(), three()];

Promise.any([one(), two(), three()])
 .then(function(values){
     console.log(values);
 })
 .catch(function() {
   console.log('rejectだよ。');
 });
----------------
2000

Promise.reject Promiseが成功か失敗か関係なく、即rejectを返すっぽい。テスト用?

function one(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    resolve(1000);
  }, 1000);
  });
}

function two(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    resolve(2000);
  }, 2000);
  });
}

function three(){
  return new Promise(function(resolve, reject){
    setTimeout(() => {
    resolve(3000);
  }, 3000);
  });
}

const promises = [one(), two(), three()];

Promise.reject([one(), two(), three()])
 .then(function(values){
     console.log(values);
 })
 .catch(function() {
   console.log('rejectだよ。');
 });

Promiseのよくわからないところ

function wait(time){
  const start = Date.now();
  while(Date.now() - start < time){
    }
  console.log(time + ' wait');
  }
  
  function waitAsync(time){
    return new Promise(function(resolve, reject) {
        const start = Date.now();
  while(Date.now() - start < time){
    }
  resolve(time);
    });
  }
  
   function waitAsync2(time){
    return new Promise(function(resolve, reject) {
        const start = Date.now();
  while(Date.now() - start < time){
    }
  resolve(time);
    });
  }

 waitAsync(1500)
  .then((time) => {
    console.log(time +' waitAsync')
  })

 waitAsync2(1000)
  .then((time) => {
    console.log(time + ' waitAsync2')
  })

wait(2000);
--------------
2000 wait 
1500 waitAsync 
1000 waitAsync2

なんでこんな順番になるんや・・・。 waitAsyncの処理で1.5秒経過(イベントキューに入る)→waitAsync2の処理で1秒経過(イベントキューに入る)→waitの処理で2秒経過、完了→waitAsync完了→waitAsync2完了ということ? イベントキューはイベントの待ち行列のこと。

https://knowledge.sakura.ad.jp/24888/

async/await

・参考 async/await 入門(JavaScripthttps://qiita.com/soarflat/items/1a9613e023200bbebcb3

・基本的な書き方

function test() {
  // 非同期処理
  return new Promise(function(resolve, reject){
    resolve(); // 成功。thenが呼ばれる
    reject(); // 失敗。catchが呼ばれる
  });
}

async function test2() {
  // 非同期処理の呼び出し。同期的に上から順に終わってから次の処理へ行く。
  await test();
  await test();
  return '成功';
}

test2().then(function() {
  // 成功時の処理
})
 .catch(function() {
   // 失敗時の処理
 });

・中身解説

// resolve1!!をreturnしているため、この値がresolveされる 
async function resolveSample() { 
    return 'resolve!!'; 
} 
// resolveSampleがPromiseを返し、resolve!!がresolveされるため 
// then()が実行されコンソールにresolve!!が表示される 
resolveSample().then(value => { 
    console.log(value); // => resolve!! 
}); 
// reject!!をthrowしているため、この値がrejectされる 
async function rejectSample() { 
    throw new Error('reject!!'); 
} 
// rejectSampleがPromiseを返し、reject!!がrejectされるため 
// catch()が実行されコンソールにreject!!が表示される 
rejectSample().catch(err => { 
    console.log(err); // => reject!! 
});

awaitとは

async function内でPromiseの結果(resolve、reject)が返されるまで待機する(処理を一時停止する)演算子のこと。 以下のように、関数の前にawaitを指定すると、その関数のPromiseの結果が返されるまで待機する。

async function sample(){
    const result = await sampleResolve();
    
    // sampleResolve()のPromiseの結果が返ってくるまで以下は実行されない
    console.log(result);}

awaitは何をするのか

  • awaitを指定した関数のPromiseの結果が返されるまで、async function内の処理を一時停止する。
  • 結果が返されたらasync function内の処理を再開する。

async/awaitのメリット

メリット1、thenを繋げないで済む。

・Promiseの例 thenが長い。

function async(param){ 
  return new Promise(function(resolve, reject) { 
  setTimeout(function(){ 
    resolve(param);
  }, 2000); 
}); 
} 
async(2000) 
  .then(function(param){ 
    console.log(param); 
    return async(4000); 
  }) 
  .then(function(param){ 
    console.log(param); 
    return async(6000); 
  }) 
  .then(function(param){ 
    console.log(param); 
  }) 
  .catch(function(error){ 
    console.log(error); 
  });

・async/awaitの例 then内で関数を呼ばず、awaitで関数を繰り返し呼ぶ。

function aaa(value) {
   return new Promise((resolve, reject) => {
     setTimeout(() => {
       resolve(value);
   }, 1000);
   });
 }
 async function bbb() {
   await aaa(1000);
   console.log(1000);
   
   await aaa(2000);
   console.log(2000);
   
   await aaa(3000);
   return 3000;
 }

bbb().then((value) => {
  console.log(value);
})
 .catch((value) => {
   console.log('fail');
 });

メリット2、ループ文で繰り返し実行できる

function sampleResolve(value) { 
    return new Promise(resolve => { 
        setTimeout(() => { 
            resolve(value); 
        }, 1000); 
    }) 
} 
async function sample() { 
    for (let i = 0; i < 5; i += 1) { 
        const result = await sampleResolve(i); 
        console.log(result); 
    } 
    return 'ループ終わった。' 
} 
sample().then((v) => { 
    console.log(v); // => 0 
                    // => 1 
                    // => 2 
                    // => 3 
                    // => 4 
                    // => ループ終わった。 
});

async/awaitの間違えやすそうなところ

同期処理が先に完了するので、let d = bbb(); はからっぽ。 thenしてあげよう。

function aaa(value) {
   return new Promise((resolve, reject) => {
       resolve(value);
   });
 }
 async function bbb() {
   const a = await aaa(1000);
   const b = await aaa(2000);
   const c =  await aaa(3000);
   return a + b + c;
 }
let d = bbb();
 console.log(d); // からっぽ
 bbb().then((value) => {
  console.log(value);
}); // こっちは6000

Promiseの戻り値には何が入ってるの?

resolve()の引数の値が入るみたい。

function aaa() {
   return new Promise((resolve, reject) => {
       resolve('abc');
   });
 }
 async function bbb() {
  const a = await aaa();
  console.log(a); // abc
 }
bbb();

なぜAjaxは画面更新せずに画面変更できるのか

よく考えたらイベントも画面更新してないよね・・・。 というかJavaScriptって基本画面更新しないよね。

btn.onclick = function() { 要素.style.color = 'red'; }

Ajaxもこれと同じだね。 Ajaxの場合はサーバーとの通信が入っているってだけだね。 なおかつ非同期なので、ユーザーは通信を待たずに済むね。 普通の通信はHTMLを丸ごと入れ替えてるから画面更新が入るね。ね。 ・初心者目線でAjaxの説明 https://qiita.com/hisamura333/items/e3ea6ae549eb09b7efb9

JavaScriptの基本

・参考 JavaScript の基本 https://developer.mozilla.org/ja/docs/Learn/Getting_started_with_the_web/JavaScript_basics

変数

変数宣言 let

JavaScriptは動的型付け言語。

let number = 9;
let string = 'あいうえお';
let boolean = true;
let boolean = false;
let boolean = 5 > 3;

String/int/booleanも全部let booleanはtrue falseのみを持つ。

定数宣言 const

const number = 10;

配列宣言

let myNameArray = ['Chris', 'Bob', 'Jim'];
let myNumberArray = [10, 15, 40];

オブジェクトの宣言

let dog = { name : 'ポチ', breed : 'ダルメシアン' };
dog.name // ポチ

テンプレートリテラル

文字列と変数をまとめて の中に書ける。 バッククオートで囲む。

const name = "あああ";
window.alert("こんにちは、" + name + "さん");//普通
window.alert(`こんにちは、'${name}さん`);// テンプレートリテラル

関数

関数宣言

戻り値の型指定いらない。

const function multiply(num1,num2) {
  let result = num1 * num2;
  return result;
}

関数呼び出し

multiply(4,7);
multiply(20,20);
multiply(0.5,3);

匿名関数

よくイベントハンドラで使われている。

function() {
  alert('hello');
}

コールバック関数

関数の引数に渡される関数のこと。 JavaScriptって引数に関数を渡せるんやで。 ここではcall()がコールバック関数。

function call() { 
  window.alert("コールバック"); 
}

//引数名()で渡されたメソッドを呼び出せる。
function abc(hikisuu) { 
  window.alert("イベントリスナー"); 
  hikisuu(); 
} 

abc(call);

※大事な事 コールバック関数ってのは別に非同期と全然関係ないんだ! 単純に関数の引数に渡される関数のことなんだぜ!!!

・参考 JavaScript中級者への道【5. コールバック関数】 https://qiita.com/matsuby/items/3f635943f25e520b7c20

コールバック関数を呼び出す側の関数は高階関数という。

条件文

演算子

イコール ===

ナットイコール !==

if

let iceCream = 'チョコレート';
if(iceCream === 'チョコレート') {
  alert('やった、チョコレートアイス大好き!');
} else {
  alert('あれれ、でもチョコレートは私のお気に入り......');
}

while

while(条件式){
}

for

for(変数の定義; 条件式; 変数の更新){}

for(let number i; i <100; i++){
}

イベント

let myHTML = document.querySelector('html');
myHTML.onclick = function() {
    alert('痛っ! つつくのはやめて!');
};

上記を略して書くとこう。

document.querySelector('html').onclick = function() {
    alert('痛っ! つつくのはやめて!');
}

イベントリスナーの種類

イベントハンドラーとイベントリスナーの違い

イベントハンドラー:  イベントに対して処理を定義したメソッド。

イベントリスナー:   イベントに対して処理を結びつける仕組み。

であり、概念としては異なるものです。

1 普通のイベント登録

const btn = document.querySelector('button'); 
btn.onclick = function() { 
  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; 
  document.body.style.backgroundColor = rndCol; 
}

2 addEventListenerで登録

const btn = document.querySelector('button'); 
function bgChange() { 
  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; 
  document.body.style.backgroundColor = rndCol; 
} 
btn.addEventListener('click', bgChange);
btn.addEventListener('click', function() { 
  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; 
  document.body.style.backgroundColor = rndCol; 
});

・イベントリスナーの削除

btn.removeEventListener('click', bgChange);

・addEventListenerの利点 削除できる。 一つのイベントに複数の関数をセットできる。

myElement.addEventListener('click', functionA);
myElement.addEventListener('click', functionB);

3 イベントハンドラーHTML属性(インラインイベントハンドラー)で登録

リスナーじゃなくてハンドラーだけど一応紹介。 onXXXのこと。 HTMLにJavaScriptが混在するので非推奨。

<button onclick="alert('Hello);">Press me</button>

・onChange属性 →input要素で何かしら変更があったときにイベントが発生する。  例えば、セレクトボックス選択時、テキスト入力後のENTER押下時。

・onClick属性 onClick="function()" クリック時にJavaScriptの関数を呼び出す。

イベントオブジェクト

https://developer.mozilla.org/ja/docs/Learn/JavaScript/Building_blocks/Events ときどきイベントハンドラー関数内で event、evt、単に e などと名付けられた引数を見かけるかもしれません。 これらはイベントオブジェクトと呼ばれ、イベントの追加機能や情報を提供する目的でイベントハンドラーに自動的に渡されます。 例えば、またランダム色の例をちょっと書き換えてみましょう。

function bgChange(e) {
  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
  e.target.style.backgroundColor = rndCol;
  console.log(e);
}

btn.addEventListener('click', bgChange);

イベントオブジェクト e が関数に含まれていて、関数内で e.target — これはボタンそのもの — の背景色スタイルを設定しているのがわかるでしょう。 イベントオブジェクトの target プロパティは、常にイベントが生じた要素への参照となっています。 ですからこの例ではページではなくボタンの背景色がランダムに変わります。

・イベントのバブリングとキャプチャリング 親子要素に同じイベント(btn.onClick()とか)をつけると順番に 発火しちゃって大変という話。

thymeleafで使えるページングのメソッド一覧

PageImplクラスのメソッドが使えるようです。

spring.pleiades.io

こんな感じでメソッド名そのままで使えるんです。 知らなかったなあ。 どういう仕組みなんだろ。

   <p th:text="${page.getSize}"></p>
    <p th:text="${page.getNumber}"></p>
    <p th:text="${page.NumberOfElements}"></p>
    <p th:text="${page.getContent}"></p>
    <p th:text="${page.hasContent}"></p>
    <p th:text="${page.isFirst}"></p>
    <p th:text="${page.nextOrLastPageable}"></p>
    <p th:text="${page.isLast()}"></p>
    <p th:text="${page.nextPageable}"></p>
    <p th:text="${page.getSort}"></p>
    <p th:text="${page.hasNext}"></p>
    <p th:text="${page.hasPrevious}"></p>
    <p th:text="${page.getTotalElements}"></p>
    <p th:text="${page.getTotalPages}"></p>
    <p th:text="${page.getPageable}"></p>
    <p th:text="${page.iterator}"></p>
    <p th:text="${page.empty}"></p>
    <p th:text="${page.totalPages}"></p>

@PageableDefaultでページのソートやサイズ指定など

spring.pleiades.io

@PageableDefaultでページのソート、サイズ指定、開始ページ指定ができるよ。

かんたんだよ。

@Controller
public class AccountController {

    @Autowired
    private Service service;

    @GetMapping("/hello")
    public String getHello(
            @PageableDefault(page = 0, size = 2, direction = Direction.DESC, sort = { "id", "name" }) Pageable pageable,
            Model model) {

        Page<AccountEntity> accountAll = service.findAllAccount(pageable);
        model.addAttribute("page", accountAll);
        model.addAttribute("accountAll", accountAll.getContent());

        return "hello";
    }
}