Skip to content

Latest commit

 

History

History
104 lines (77 loc) · 4.9 KB

promise-and-array.adoc

File metadata and controls

104 lines (77 loc) · 4.9 KB

Promiseと配列

ここまでで、promiseオブジェクトが Fulfilled または Rejected となった時の処理は .then.catch で登録でき、 .finally を使うことで Fulfilled と Rejected どちらの場合でも実行される処理を登録できることを学びました。

一つのpromiseオブジェクトなら、そのpromiseオブジェクトに対して処理を書けばよいですが、 複数のpromiseオブジェクトが全てFulfilledとなった時の処理を書く場合はどうすればよいでしょうか?

たとえば、複数のXHR(非同期処理)が全て終わった後に、何かをしたいという事例を考えてみます。

少しイメージしにくいので、 まずは、通常のコールバックスタイルを使って複数のXHRを行う以下のようなコードを見てみます。

Warning
CORSについて

ブラウザにおけるXHRのリソース取得には、CORS(Cross-Origin Resource Sharing)というセキュリティ上の制約が存在します。

このCORSの制約により、ブラウザでは同一ドメインではないリソースを許可なく取得することはできません。そのため、一般的には別サイトのリソースは許可なくXHRでアクセスすることができません。

次のサンプルでは https://azu.github.io/promises-book/json/comment.json という azu.github.io ドメイン以下にあるリソースを取得する例が登場します。

azu.github.io ドメイン以下のJSONには、別ドメインからの取得が許可する設定がされています。

また、 httpbin.org というドメインがリソース取得の例として登場します。 こちらも、同一ドメインでなくてもリソースの取得が許可されています。

コールバックで複数の非同期処理

multiple-xhr-callback.js
link:embed/embed-multiple-xhr-callback.js[role=include]
// 実行例
main(function(error, results){
    if(error){
        console.error(error);
        return;
    }
    console.log(results);
});

このコールバックスタイルでは幾つかの要素が出てきます。

  • JSON.parse をそのまま使うと例外となるケースがあるためラップした jsonParse 関数を使う

  • 複数のXHRをそのまま書くとネストが深くなるため、allRequest というrequest関数を実行するものを利用する

  • コールバック関数には callback(error,value) のように第一引数にエラー、第二引数にレスポンスを渡す。

jsonParse 関数を使うときに bind を使うことで、部分適用を使って無名関数を減らすようにしています。 (コールバックスタイルでも関数の処理などをちゃんと分離すれば、無名関数の使用も減らせると思います)

jsonParse.bind(null, callback);
// は以下のように置き換えるのと殆ど同じ
function bindJSONParse(error, value) {
    jsonParse(callback, error, value);
}

コールバックスタイルで書いたものを見ると以下のような点が気になります。

  • 明示的な例外のハンドリングが必要

  • ネストを深くしないために、requestを扱う関数が必要

  • コールバックがたくさんでてくる

次は、Promise#then を使って同様のことをしてみたいと思います。

Promise#thenのみで複数の非同期処理

先に述べておきますが、Promise.all というこのような処理に適切なものがあるため、 ワザと .then の部分をクドく書いています。

.then を使った場合は、コールバックスタイルと完全に同等というわけではないですが以下のように書けると思います。

multiple-xhr.js
link:embed/embed-multiple-xhr.js[role=include]
// 実行例
main().then((value) => {
    console.log(value);
}).catch((error) => {
    console.error(error);
});

コールバックスタイルと比較してみると次のことがわかります。

  • JSON.parse をそのまま使っている

  • main() はpromiseオブジェクトを返している

  • エラーハンドリングは返ってきたpromiseオブジェクトに対して書いている

先ほども述べたように mainの then の部分がクドく感じます。

Promiseでは、このような複数の非同期処理をまとめて扱う Promise.allPromise.race という静的メソッドが用意されています。

次のセクションではそれらについて学んでいきましょう。