update.JavaScriptのPromiseについて。JSはシングルスレッドで、ひとつ処理が終了したら次の処理を実行、という形で、通常は同期処理がおこなわれる。1同期処理では、1つの処理が詰まると次の処理が行われない。etc.)そのため、非同期処理ももちろん用意されている。非同期処理1つの処理の終了を持たないまま別の処理に進める方法。jQueryの$.ajaxなどが挙げられる。API1にリクエストしてアイテムの一覧を取得した後、API2で先頭のアイテムの詳細情報を取得、という処理を書くとする。関数にコールバックを渡す形式にする。successProcess(item);});また、1番目のアイテムを取得した後に2番目も取得しようとすると、例えば以下のようになる。各アイテムの取得のリクエストを同時に行い、全てレスポンスが返ってきてから描画、といった並列処理などを行うとなったらどうするか?なかなか辛そう。非同期処理の関数にコールバック関数を引数として渡す非同期処理を行うオブジェクトにコールバック関数を登録etc.といった課題があった。そこで登場したのがPromise。オブジェクト非同期処理を行う関数はPromiseを戻り値として返し、呼び出し側はPromiseにコールバック関数を登録https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PromiseES2015で導入、ブラウザ対応状況Promiseを使うと、上記の処理は以下の様な感じになって短く書けるようになる。}});こうして生成したPromiseオブジェクトは、thenとセットで使う。error.message);});Promiseの使い方の基本は以下。rejectedの状態に変化する。この状態の変更は一方通行で、pendingに戻ることはない。状態変更が起こった時に実行する関数を登録できるのがthen()。指定時間後に何らかの処理を実行する関数waitを実装する。console.log(value);});setTimeoutという非同期アクションの実行結果に応じた処理が行われる(上記は処理成功が前提になっているが)。waitは未来のある時点でPromiseを返す。Promiseを利用することで、同期処理と同じように値を返せるようになった。3000"と"undefined"が出力される。3000undefinedthenのメソッドチェーン上記の例では、3つのthen()を繋げている。先述したように、then()が返すのもPromiseオブジェクトであるためこのようなことが可能、何個でもチェーンできる。<値>することは、resolve(<値>)と等しい何もreturnしないときは、resolve()と同じこのようなルールがある。詳細を取得する非同期処理をもう一度。console.error(e);});getUrl()でPromiseを返し、通信の成功/失敗で処理を分岐させる。getFirstItem()で、2つのAPIエンドポイントに順次リクエストし、最後まで処理が完了したらsuccessProcess()、失敗したらエラーを出力。then()のチェーンの最後に付けておけば、一連の処理中にreject()で明示的に処理失敗を宣言した場合だけでなく、予想外のエラーも拾ってくれる。これまで書いてきたが、Promiseが統一的なインターフェースを提供してくれるおかげで、コードの見通しがだいぶ良くなる。これだけで終わりではなく、非同期処理の並列実行/直列実行も簡単に実装できるようになる。並列処理APIを多数コールし、全てのレスポンスが返った後に処理を行う、という場合はPromise.all()を使うと楽に書ける。console.error(error);});コードを実行すると、以下の出力に。Cの処理は配列のインデックス順にほぼ同時に開始され、task()の最初のconsole.logが実行される。その後処理はsetTimeoutに到達し、コールバック実行までの時間が最も短いtaskCから順にresolve()され、それと同時にログに出力が行われる。3,000ms後にAのPromiseがfullfilledになる。結果、taskAが終了した約3,000ms後に、catch()ではなくthen()の引数のコールバック関数が実行される。コールバック関数の引数(values)には、並列処理したそれぞれのPromiseがresolve()で返した値が配列として入っているのが分かる。なるのを待ってから処理を行ってくれるため、冒頭に書いたような「APIを多数コールし、全てのレスポンスが返った後に処理を行う」ケースなどで非常に有用である。.catch(...);数が増えると少しめんどいし、見難くなってくる。Array.prototype.reduce()を使う調べるとよく出てくるやり方。Promise.resolve());tasks.catch(...);reduce()を使ってチェーンを繋げていく方式。(同様にPromise.reject()も存在する)これでも良さげだが、さらに良いやり方があるらしい。Generatorというのを利用する。非同期処理を同期処理のように書けるようになるここはまだちょっと理解が怪しいGeneratorの利用例Generatorを使った簡単なコードを書いてみる。ジェネレータ関数は、functionと関数名の間に*を付けて定義する。ここで欠かせないのがyield。}ジェネレータ関数は実行するとイテレータを返し、nextメソッドというのを持っている。これを実行すると、generator()内の最初のyieldまで実行され、yield式の結果をvalueとして返す。nextを実行すると次のyieldまで実行される。returnあるいは実行するyieldが無くなると、イテレータのdoneがtrueになる。簡単な例で示したが、このようにGeneratorを利用することで、関数内の処理の中断・再開を行える。非同期処理の直列処理Generatorを利用したPromiseの直列処理も簡単に書ける。ここではcoというライブラリを利用する。返したら再開、という挙動になり、結果として非同期処理が逐次処理される。次の世代のECMAScriptでは、async/awaitという機能で、このGeneratorが標準搭載されるそう。PromisesGeneratorは新しい概念だが、逐次処理などで有用もうちょい学習が必要かな。組織改善プラットフォームwevoxなどのサービスを運営。全ての社員が誇りを持てる組織と事業の創造にこだわり、関わる人々がファンとして応援したくなるような魅力ある会社であり続けることを目指しています。upLoginユーザーは見つかりませんでした。