【非同期処理】Promise,async/awaitについて


## まず、反対の同期処理とは
プログラムの記述順序通りに実行され結果が返る。
add関数が実行され計算結果がリターンされてから、hogeに代入している。
⇓
JavaScriptは「UIスレッド」と呼ばれるメインスレッド上で処理を１つ１つ順番に実行していくことしかできない。
⇓
時間のかかる処理を行うとJavascriptはその処理にUIスレッドを占有してしまう。処理完了まで一切何もできなくなる。クリックもローダーやプログレスバーの表示もできない。つまり、パソコンがフリーズしているように見えやすい
```javascript:test1.js
//例１
cosnt add = (a, b) => {
	return a + b
}

let hoge = 0;
hoge = add(10, 100)
console.log(hoge) //表示は「110」
```
```javascript:test2.js
//例２
//10秒間UIスレッドを独占する。その間は操作できない
function sleep(msec) {
	var start = new Date();
	while (new Date() - Start < msec);
	alert("処理完了");
}

sleep(10000);
```

以下本題⇓
## 非同期処理とは
例：Amazon, GoogleMapとか

超簡単に言うと：
非同期処理は、あるタスクが実行している際に、他のタスクが別の処理を実行できる方式である。

メリット：ユーザ体験が上がる！
２つの例で見てきたようにサクサク動きながらデータを取ってこようと思ったら非同期処理を活用しないと著しくユーザ体験が低くなってしまう。

自分がよくしてしまったmiss！⇓
```javascript:test.js
// 第3引数がfalseで同期
new XMLHttpRequest().open("GET", "https://zip-cloud.appspot.com/api/search?zipcode=7830060",false);
```
警告文
解説：XMLHttpRequestは非同期処理で使用しなければならない。さもないと、ユーザー体験に悪影響を与える...
(読みにくいの改行してます）
```javascript:test.js
// Synchronous XMLHttpRequest on the main thread is deprecated 
// because of its detrimental effects to the end user's experience. 
// For more help, check https://xhr.spec.whatwg.org/.
```

## Promise型について
Promise型は非同期処理を実現する
Promiseを作るには非同期処理の内容を記述した関数を引数に指定し、Promiseのインスタンスを生成します。
基本的な形は⇓
```javascript:test.js
new Promise((resolve, reject) => {
//処理を書く
});
```
## APIの取得について
（ここが難しいというか、理解しづらい。）
JavaScriptでAPI取得する
```javascript:test1.js
function question() {
	return new Promise((resolve, reject) => {
		let req = new XMLHttpRequest();
		req.onreadystatechange = function() {
			if (req.readyState == 4) { // 通信の完了時
				if (req.status == 200) { // 通信の成功時
					let data = eval('(' + req.responseText + ')');
					resolve(data.answer);
				}
			} else{
				console.log("通信中...");
			}
		}
		req.open('GET', 'エンドポイント', true);
		req.send(null);
	});
}
question().then(
	function(val) {
		console.log('answer:' + val)
	},
	function(err) {
		console.log(err)
	}
);
```


ここでPromise型をうまく使うと効果抜群！
めっちゃ簡単に言うと：
json取得 → 画像読み込み完了 → 表示の非同期処理の実行
この順番をきれいに整理してUXをよくするってことだと思う。

つまり、読み込み完了まではローディング画像をセットし、完了後に読み込んだ画像を表示している。
```javascript:test2.js
function question() {
	return new Promise((resolve, reject) => {
		let req = new XMLHttpRequest()
		req.onreadystatechange = function() {
			if (req.readyState == 4) { // 通信の完了時
				if (req.status == 200) { // 通信の成功時
					let data = eval('(' + req.responseText + ')')
					resolve(data)//先ほどはdata.answerだった
				}else {
					reject(req.status)//先ほどからの付け加え
				}
			} else{
				console.log("通信中...")
			}
		}
		req.open('GET', 'エンドポイント', true)
		req.send(null)
	})
}
//以下Promise型をうまく使えているところ
function imageLoaded(src) {
	return new Promise((resolve, reject) => {
		let img  = new Image()
		img.src = src
		img.addEventListener("load", () => {
			resolve(src)
		})
	})
}
question().then(
	(data) => {
		this.answer = data.answer
		this.status = 1
		return imageLoaded(data.image)
	},
	(err) => {
		console.log(err)
	}
).then(
	(src) => {
		this.image = src
		this.status = 2
	}
)
```

## async/await
以下、async/awaitで書き換えると、めちゃシンプル
関数の前にasyncを付けると、async関数になる。
演算子awaitはasync関数の中でのみ使えるもので、対象のPromiseが成功するまで待ってくれます。 さきほどのコードのプロミスの連鎖箇所をasync,awaitで書き換えています。

```javascript:test3.js
let display = async () => {
	try {
		await question()
		await imageLoaded()
	} catch(err) {
		console.log("エラーが起こりました:" + err)
	}
}
display()
```


## 最後に
わかりにくいところ、おかしいところあれば教えてくださるとうれしいです。