約束に関する優れた記事の最初の部分の翻訳。 約束を作成および管理するための基本的なテクニック。
約束は、計算に無期限の時間がかかる操作に使用されます。 このような操作の例としては、APIからデータを要求するときのネットワーク要求があり、応答がいつ受信されるかを正確に判断することはできません。
実行がこのネットワーク要求に依存する他の操作がある場合、問題が発生します。 約束がなければ、一連のコールバックを使用して一連の操作を作成する必要があります。 非同期アクションが1つある場合、これは正常です。 しかし、いくつかの連続した非同期ステップを実行する必要がある場合、コールバックは制御不能になり、結果はコールバック地獄として悪名高いです
doSomething(function(responseOne) { doSomethingElse(responseOne, function(responseTwo, err) { if (err) { handleError(err); } doMoreStuff(responseTwo, function(responseThree, err) { if (err) { handleAnotherError(err); } doFinalThing(responseThree, function(err) { if (err) { handleAnotherError(err); } // }); // doFinalThing }); // doMoreStuff }); // doSomethingElse }); // doSomething
Promiseは、連続して実行する必要があるタスクを解決するための標準化された理解可能な方法を提供します。
doSomething() .then(doSomethingElse) .catch(handleError) .then(doMoreStuff) .then(doFinalThing) .catch(handleAnotherError)
約束の作成
Promiseは、Promises Designerを使用して作成されます。 パラメーターとして2つの引数( resolve
& reject
)を持つ関数です。
var promise = new Promise(function(resolve, reject) { /* */ } )
この関数内で、非同期タスクを実行できます。 promiseを実行済みとしてマークするには、 resolve()
を呼び出して、返す値を渡します。 約束を拒否または失敗としてマークするには、 reject()
を呼び出して、エラーメッセージを渡します。 約束が満たされるか拒否される前に、それは期待の状態にあります。
XMLHttpRequestの有望なバージョンは次のとおりです-
/* CREDIT - Jake Archibald, http://www.html5rocks.com/en/tutorials/es6/promises/ */ function get(url) { return new Promise(function(resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', url); req.onload = function() { if (req.status == 200) { resolve(req.response); /* */ } else { reject(Error(req.statusText)); /* */ } }; req.onerror = function() { reject(Error("Network Error")); }; req.send(); }); }
Promiseの使用
約束を実行するために、通常の関数のようにそれを呼び出すことができます。 ただし、これは約束であるため、関数に追加できる.then
メソッドにアクセスできます。このメソッドは、約束がスタンバイモードを終了するときに実行されます。
.then()
メソッドは、2つのオプションパラメータを受け入れます。 1つ目は、promiseが実行(解決)されるときに呼び出される関数です。 2番目は、約束が拒否された場合に実行される関数です。
get(url) .then(function(response) { /* successFunction */ }, function(err) { /* errorFunction */ })
エラー処理
両方のパラメーター(successFunctionおよびerrorFunction)はオプションであるため、読みやすくするために2つの.then()
分割できます。
get(url) .then(function(response) { /* successFunction */ }, undefined) .then(undefined, function(err) { /* errorFunction */ })
コードをさらに理解しやすくするために、 .catch()
メソッドを使用できます。これは、 .then(undefined, errorFunction)
省略形です
get(url) .then(function(response) { /* successFunction */ }) .catch(function(err) { /* errorFunction */ })
連鎖
promiseの本当の価値は、いくつかの非同期関数を順番に実行できることです。 .then()
と.catch()
を組み合わせて、非同期関数のシーケンスを作成できます。
これを行うには、前の約束を完了または拒否した後、別の約束を返します。 たとえば-
get(url) .then(function(response) { response = JSON.parse(response); var secondURL = response.data.url return get( secondURL ); /* */ }) .then(function(response) { response = JSON.parse(response); var thirdURL = response.data.url return get( thirdURL ); /* */ }) .catch(function(err) { handleError(err); });
約束が解決されると、シーケンス内の最も近い.then()
が呼び出されます。 約束が拒否された場合、シーケンス内の最も近い.catch()
。
並列約束
いくつかのプロミスを並行して実行し、すべてのプロミスが完了した後にのみアルゴリズムを続行する必要がある場合に、状況が発生する可能性があります。 たとえば、一連の画像を取得したい場合にのみ、その画像をページに表示します。
これを行うには、2つの方法を使用する必要があります。 これは、配列の各要素にプロミスを適用し、結果を新しい配列に保存するためのArray.map()
です。 Promise.all()
は、配列内のすべてのPromise.all()
が実行されるとresolve()
を実行します。 配列内の少なくとも1つのプロミスが拒否された場合、 Promise.all()
も拒否されます。
var arrayOfURLs = ['one.json', 'two.json', 'three.json', 'four.json']; var arrayOfPromises = arrayOfURLs.map(get); Promise.all(arrayOfPromises) .then(function(arrayOfResults) { /* -, */ }) .catch(function(err) { /* , */ })
開発ツールの[ネットワーク]パネルを見ると、すべてのリクエストが並行して発生していることがわかります。
IEやOpera Miniのサポートが必要な場合は、 polyfilを使用してください 。
ご清聴ありがとうございました!