それはすべて、インタビューのテスト作業として、応募者にJSに写真のプリローダーを実装するように依頼することから始まりました。 プリロード自体に加えて、スクリプトは、目的のイメージをロードできなかった場合に代替イメージを代用できる必要があります。 前提条件は、ES6 Promiseの使用でした。
それから私は考えた:「なぜこのようなプリローダーを自分で実装して、一般的な使用に入れてみませんか? はい、Habrに関する記事を書く絶好の機会です!」
実際には、カッターの下で、そのようなプリローダーのロジックの説明+プリローダー自体へのリンク。
まず、JSの約束が何であるかを思い出しましょう。
約束について
Promisは、まず、非同期コードを整理する方法です。 必ずしも非同期ではありませんが...
約束を作成するには、約束が作成された直後に実行される関数が必要です。
この関数内のタスクは、この関数に渡される2つのメソッドのいずれかを自動的に呼び出すことです-解決または拒否。
これらのメソッドのいずれかを呼び出すことにより、タスクのステータスについての約束を伝えます:正常に完了(解決)または失敗(拒否)。
これは、タスクが成功または失敗した場合に、さらなるアクションのチェーンを構築できるようにするために行われます。
var p = new Promise(function(resolve, reject) { someAsycOperation(function(e, result) { if (e) { reject(e); } else { resolve(result); } }); });
それから
各promiseにはthenメソッドがあり、引数として2つの関数(then-callbacks)を取ります。
1つ目はonFulfilledコールバックとも呼ばれ、タスクが正常に完了した場合に実行され、2つ目はonRejectedコールバックとも呼ばれます-タスクが失敗した場合です。
しかし、タスクのステータスを約束するまで、これらの2つの関数は呼び出されません。
thenメソッドは別のプロミスを返しますが、これは解決または拒否することも、ハングさせることもできます。
そして円で...
resolveまたはrejectを呼び出すときに引数を渡すと、この引数は次のコールバックに転送され、現在のタスクの完了後に実行されます。
var p = new Promise(function(resolve, reject) { someAsyncOperation(function(e, result) { if (e) { reject(e); } else { resolve(result); } }); }).then(function(value) { //on success .... }, function(e) { //on fail console.error(e); });
Then-callbackは、returnステートメントを使用して単に値を返す、次のthen-callbackに値をスローすることもできます。
var p = new Promise(function(resolve, reject) { someAsyncOperation(function(e, result) { if (e) { reject(e); } else { resolve(result); } }); }).then(function(value) { //on success ... return 'some value'; }, function(e) { //on fail console.error(e); }).then(function(value) { //value === 'some value' });
状態について
開始関数内では、タスクの結果を報告する方法は3つしかありません。
成功しました:
- コール解決
失敗:
- コール拒否
- 例外を投げる
その中の関数には小さなルールがあります:
つまり、then-callbackが例外をスローするか、拒否状態の別のプロミスを返す場合、promise全体が拒否状態になり、他のすべての場合、promiseは解決済み状態になります(then-callbackが何も返さない場合でも)。
当時のコールバックルールを見て、最後の例を見てください...
非同期操作が成功すると、最初のthenでonFulfilledコールバックが実行され、2番目のthenでonFulfilledコールバックが実行されます。
しかし、非同期操作が失敗するとどうなりますか? 最初のthenでonRejectedコールバックが実行され、2番目のthenで( 注意! )OnFulfilledコールバックが実行されます。
なんで? then-callbackについては上記のルールをご覧ください。
それから進んで、次のonRejectedコールバックを呼び出すために(これはありません)、拒否するプロミスを返すか、例外をスローする必要があります。
ちなみに、何らかの理由でonRejectedコールバック、つまり速記のcatch()メソッドだけを約束する必要がある場合
var p = new Promise(function(resolve, reject) { console.log(' '); someAsyncOperation(function(e, result) { if (e) { reject(e); } else { resolve(result); } }); }).catch(function(e) { console.log(' '); console.error(e); }).then(function() { console.log(' !'); });
または、その後使用する場合、onFulfilled-callbackの代わりにnullを渡すことができます。
しかし、トピックに戻って...何が起こるか見てください...
最初のonRejectedコールバックは、一種のフォールバックアクションの役割を果たします。 次に、チェーンは非同期操作が成功したかのように進みます。
var p = new Promise(function(resolve, reject) { console.log(' '); someAsyncOperation(function(e, result) { if (e) { reject(e); } else { resolve(result); } }); }).then(function(result) { console.log(' '); }, function(e) { console.log(' '); console.error(e); }).then(function() { console.log(' !'); });
JSの約束はすでに箱から出しており、フォールバックアクションをサポートしていることがわかります。
そして今、約束したように、壊れた画像をデフォルトの画像で置き換える機能を実装する画像プリローダーへのリンクを提供します。
先ほど説明したその動作の原理。
ところで、プリローダーはallSettled関数を使用しますが、その操作はフォールバックアクションの同じ原理に基づいています。
また、コードに精通することをお勧めします。
ご清聴ありがとうございました!
PSは怠け者ではありません-promiseのドキュメントを読んでください!