Promise
非同期処理ってなに?
- あるタスクを実行している間、そのタスクの完了を待たずに他のタスクを実行できる方法。
- JavaScriptで非同期処理を行う場合は、
Promise
オブジェクトまたはAsync/Await
構文で記述する。
どうやって書くの?
非同期処理の代表的な関数としてsetTimeout(コールバック関数, delay)
関数を使用した例を挙げる。
Promise
オブジェクトを利用する場合と、async/await
構文を利用する場合の書き方を綴る。
Promiseオブジェクト
- 非同期処理は
Promise
インスタンスを返す。 Promise
インスタンスには処理に成功した際(resolve
)/失敗した際(reject
)に呼ばれるコールバック関数を登録できる。- 非同期処理に成功したら
resolve()
を呼び、then()
内のコールバック関数で記述した処理を実行する。 - 非同期処理に失敗したら
reject()
を呼び、catch()
内のコールバック関数で記述した処理を実行する。
new Promise((resolve, reject) => { try { // ここで非同期処理を実行する // 非同期処理が成功したらresolveを呼ぶ resolve(); } catch (e) { // 非同期処理に失敗したらrejectを呼ぶ reject(); }}).then(() => { // 非同期処理が成功した際の処理}).catch(() => { // 非同期処理が失敗した際の処理})
// ちなみにtry...catch構文を使わなくても、Promiseオブジェクトでは例外が自動でキャッチできる!
const func = new Promise((resolve, reject) => { // 非同期処理を実行する // 非同期処理が成功したらresolveを呼ぶ resolve(); // 非同期処理に失敗したらrejectを呼ぶ reject();});
// then()でコールバック関数を登録// 第一引数に成功した際に呼ばれる無名関数の変数名、// 第二引数に失敗した際に呼ばれる無名関数の変数名を指定するfunc.then(resolved, rejected);
const resolved = () => { // 非同期処理が成功した際の処理};
const rejected = () => { // 非同期処理に失敗した際の処理};
例: 非同期処理を使わない場合
// 通常let a = 0;console.log(a); // 「0」が出力される。
setTimeout(() => { a = 1;},3000);console.log(a); // ここも「0」が出力される。a = 1は3000ms後に実行され、ここの処理は3000ms待ってくれない。
00
例: 非同期処理を使う
let a = 0;console.log(a);
new Promise((resolve, reject) => { // new Promise()でPromiseをインスタンス化する setTimeout(() => { a = 1; resolve(); // 処理が終わってresolve()を実行すれば、then()に移行する。 }, 3000);}).then(() => { console.log(a);});
01 #PromiseでsetTimeout内の処理を待った
例: 処理の値をコールバック関数で使いたい時
let a = 0;console.log(a);
new Promise((resolve, reject) => { setTimeout(() => { a = 1; resolve(a); // resolve()の引数に処理の値を指定すれば、then()で使える。 }, 3000);}).then((b) => { console.log(b);}).catch(() => { console.log('catch!');});
01
例: 複数のコールバック関数を使いたい時
let a = 0;console.log(a);
new Promise((resolve, reject) => { setTimeout(() => { a = 1; resolve(a); }, 3000);}).then((b) => { console.log(b); b = b + 1; return b; // 次のthen()に値を渡す場合は、returnで戻り値を指定してあげる。}).then((b) => { // .then()を繋げれば上から順に実行される。 console.log(b);}).catch(() => { console.log('catch!');});
async/await
let a = 0;console.log(a);
// 3秒後に引数の2倍の値を返す関数function twice(value) { return new Promise((resolve, reject) => { setTimeout(() => { value = value * 2; resolve(value); }, 3000); })}
// twice()を呼び出す関数async function sample() { // awaitを使った関数(呼び出し元)の前方にasyncをつける。 const a = await twice(1); // 待ってあげたい処理の先頭にawaitをつける。 return a;}
sample().then((r) => { console.log(r);});
// 複数の処理を待ちたい時async function sample2() { const a = await twice(1); const b = await twice(2); const c = await twice(3); return a + b + c;}
sample2().then((r) => { console.log(r);});
// 複数の処理を並列で処理したい時async function sample3() { const [a, b] = await Promise.all([twice(10), twice(20)]); return [a, b];}
sample3().then((r) => { console.log(r);});
// await// awaitを使って待ちたい処理(関数)からPromiseの結果が返されるまでasync function内の処理を止める。
// async// asyncはPromiseの結果を返す。// asyncが値をreturnをした場合、Promiseはresolveと戻り値を返す。// asyncが例外またはthrowした場合、Promiseはrejectを返す。