Skip to content

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待ってくれない。
console
0
0

例: 非同期処理を使う

非同期処理で実行する
let a = 0;
console.log(a);
new Promise((resolve, reject) => { // new Promise()でPromiseをインスタンス化する
setTimeout(() => {
a = 1;
resolve(); // 処理が終わってresolve()を実行すれば、then()に移行する。
}, 3000);
}).then(() => {
console.log(a);
});
console
0
1 #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!');
});
console
0
1

例: 複数のコールバック関数を使いたい時

複数のコールバック関数を使いたい時
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を返す。