JavaScript
es6

Promise再入門① ~Promise基本編~

More than 1 year has passed since last update.


概要

PromiseはモダンJSでコーディングする際の肝の1つです。

Promiseを制するものが、モダンJSを制するものと言っても言い過ぎではないと思います。

ES7では、いよいよasync/awaitが実装されます。

今まで感覚で使っていた部分もあるPromiseを再度学習し直そうと思います。


Promiseとは


  • 非同期の処理を分かりやすく制御するオブジェクト

  • ES6に追加された機能の1つ

  • IE対応用のPolyfillも完備


Promiseの使い方


  • Promiseはnewして使う。

  • Promiseオブジェクトの第1引数は必ず関数


    • Promiseの第1引数の関数はは 成功時の処理失敗時の処理 を実行する引数(関数)を取得できる。

    • 成功 -> resolve(渡したい値)

    • 失敗 -> reject(渡したい値)



  • newされたPromiseは以下の関数を持つオブジェクトを返す


    • then(onFulfilled,onRejected),catch(onRejected)

    • thenでresolveされた時の処理、catchでrejectされた時の処理を受け取る

    • thenもcatchも引数を持つ関数を引数に取る

    • catchはエラーの処理が明確になるだけでなく、複数の非同期処理のエラーをまとめて制御する為にも使用される

    • 基本的には、catchを使って失敗時の処理を記述する




const promise = new Promise((resolve, reject) => {
window.setTimeout(() => {
resolve('OK');
}, 2000);
});

promise
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
});


Promiseパターン


Promiseを使って同期的に処理


  • thenの中でPromiseを返せば、さらにthenを続けて記載する事が可能

  • 今回の例では、同期的に処理される。


    • func1の非同期処理の完了後、func2がコールバックされて、func2の非同期が完了後、次のthenに移っている。

    • Promiseを返さなければ、並列で処理されるthenとなる




const func1 = (num) => {
return new Promise((resolve) => {
window.setTimeout(() => {
resolve(num);
}, 3000);
});
};

const func2 = (num) => {
return new Promise((resolve) => {
window.setTimeout(() => {
resolve(num * num);
}, 2000);
});
};

func1(2)
.then(func2)
.then((result) => {
console.log(result);
})
.catch((e) => {
console.log(e);
});


  • コールバック地獄が容易に想像出来るが下記の様な書き方も可能


...

func1(2)
.then((res1) => {
func2(res1)
.then((res2) => {
console.log(res2);
});
});


Promiseを使って並列処理して完了を検知する


  • 複数の非同期処理を並列で実行し、全てが完了したら情報を取得する


    • 非同期のメリット




  • Promise.all([Promise, Promise...])を使って、非同期な処理を並列で行い、全てがresolveになるタイミングでthenを取得する。

  • 並列処理しているもので1つでもrejectがあれば、catchされる。


const func1 = (num) => {
return new Promise((res) => {
window.setTimeout(() => {
res(num + num);
}, 500);
});
};

const func2 = (num) => {
return new Promise((res, rej) => {
window.setTimeout(() => {
rej(num * num);
}, 2000);
});
};

Promise.all([
func1(2),
func2(3)
])
.then((results) => {
console.log(results);
})
.catch((e) => {
console.log(e);
});


1つでも処理が返ってきたら実行する



  • Promise.race([Promise, Promise...])を使う事で、resolveもcatchでも何かしら処理が返ってきたら次の処理(thenやcatch)を実行する様に出来る。


const func1 = (num) => {
return new Promise((res) => {
window.setTimeout(() => {
res(num + num);
}, 500);
});
};

const func2 = (num) => {
return new Promise((res, rej) => {
window.setTimeout(() => {
rej(num * num);
}, 2000);
});
};

Promise.race([
func1(3),
func2(3)
])
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e);
});


終わり

今回は基本編という事で、Promiseオブジェクトの最低限の知識をまとめました。

次回は、ES7で実装されるasync/awaitを使って、より柔軟にPromiseを使って見たいと思います。