サマリー: このチュートリアルでは、JavaScript Promise.race()
static メソッドの使い方について学びます。
JavaScript Promise.race() static メソッドの概要
Promise.race()
static メソッドは、イテラブル オブジェクトとして プロミス のリストを受け取り、プロミスが1つでも解決するか拒否されるとすぐに解決または拒否される新しいプロミスを、そのプロミスからの値または理由で返します。
Promise.race()
メソッドの構文はこちらです
Promise.race(iterable)
Code language: JavaScript (javascript)
この構文で、iterable
はプロミスのリストを含む イテラブル オブジェクト です。
Promise.race()
の名前は、すべてのプロミスが 1 つの勝者(解決または拒否)となって競争していることを示しています。
次の図を参照してください
この図で
promise1
はt1
で値v1
で解決されます。promise2
はt2
でerror
で拒否されます。promise1
はpromise2
より早く解決されるため、promise1
がレースに勝ちます。そのため、Promise.race([promise1, promise2])
はt1
で値v1
で解決される新しいプロミスを返します。
別の図を参照してください
この図で
promise1
はt2
でv1
で解決されます。promise2
はt1
でerror
で拒否されます。promise2
はpromise1
より早く解決されるため、promise2
がレースに勝ちます。そのため、Promise.race([promise1, promise2])
はt1
でerror
で拒否される新しいプロミスを返します。
JavaScript Promise.race() の例
Promise.race()
static メソッドを使用する例をいくつか見てみましょう。
1) シンプルな JavaScript Promise.race() の例
次のコードは 2 つのプロミスを作成します。1 つは 1 秒後に解決し、もう 1 つは 2 秒後に解決します。最初のプロミスは 2 番目のプロミスよりも早く解決されるため、Promise.race()
は最初のプロミスからの値で解決します
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('The first promise has resolved');
resolve(10);
}, 1 * 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('The second promise has resolved');
resolve(20);
}, 2 * 1000);
});
Promise.race([p1, p2])
.then(value => console.log(`Resolved: ${value}`))
.catch(reason => console.log(`Rejected: ${reason}`));
Code language: JavaScript (javascript)
出力
The first promise has resolved
Resolved: 10
The second promise has resolved
次の例は、2 つのプロミスを作成します。最初のプロミスは 1 秒後に解決しますが、2 番目のプロミスは 2 秒後に拒否されます。最初のプロミスは 2 番目のプロミスよりも早いため、返されるプロミスは最初のプロミスの値に解決します
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('The first promise has resolved');
resolve(10);
}, 1 * 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('The second promise has rejected');
reject(20);
}, 2 * 1000);
});
Promise.race([p1, p2])
.then(value => console.log(`Resolved: ${value}`))
.catch(reason => console.log(`Rejected: ${reason}`));
Code language: JavaScript (javascript)
出力
The first promise has resolved
Resolved: 10
The second promise has rejected
2 番目のプロミスの方が 1 番目のプロミスよりも早ければ、返されるプロミスは 2 番目のプロミスの理由で拒否されます。
2) 実践的な JavaScript Promise.race() の例
サーバーからのデータロード処理が一定秒数を超えた場合にスピナーを表示する必要があるとします。
これを実現するには、Promise.race()
static メソッドを使用できます。タイムアウトが発生した場合、ローディングインジケータを表示し、そうでない場合、メッセージを表示します。
以下は HTML コードの例です
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript Promise.race() Demo</title>
<link href="css/promise-race.css" rel="stylesheet">
</head>
<body>
<div id="container">
<button id="btnGet">Get Message</button>
<div id="message"></div>
<div id="loader"></div>
</div>
<script src="js/promise-race.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
ロードインジケーターを作成するために CSS のアニメーション機能を使用します。詳しくは、promise-race.css
をご覧ください。技術的に言うと、要素に .loader
クラスがあると、ロードインジケーターが表示されます。
最初に、データをロードする新しい関数を定義します。非同期処理をエミュレートするために setTimeout()
を使用します。
const DATA_LOAD_TIME = 5000;
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const message = 'Promise.race() Demo';
resolve(message);
}, DATA_LOAD_TIME);
});
}
Code language: JavaScript (javascript)
次に、コンテンツを表示する関数を開発します。
function showContent(message) {
document.querySelector('#message').textContent = message;
}
Code language: JavaScript (javascript)
また、この関数は message
を空白に設定するためにも使用できます。
3つ目に、プロミスを返す timeout()
関数を定義します。指定された TIMEOUT
が渡されると、プロミスは拒否されます。
const TIMEOUT = 500;
function timeout() {
return new Promise((resolve, reject) => {
setTimeout(() => reject(), TIMEOUT);
});
}
Code language: JavaScript (javascript)
4つ目に、ロードインジケーターを表示して非表示にする関数を開発します。
function showLoadingIndicator() {
document.querySelector('#loader').className = 'loader';
}
function hideLoadingIndicator() {
document.querySelector('#loader').className = '';
}
Code language: JavaScript (javascript)
5つ目に、メッセージを取得ボタンにクリックイベントリスナーを追加します。クリックハンドラー内で、Promise.race()
スタティックメソッドを使用します。
// handle button click event
const btn = document.querySelector('#btnGet');
btn.addEventListener('click', () => {
// reset UI if users click the 2nd, 3rd, ... time
reset();
// show content or loading indicator
Promise.race([getData()
.then(showContent)
.then(hideLoadingIndicator), timeout()
])
.catch(showLoadingIndicator);
});
Code language: JavaScript (javascript)
Promise.race()
メソッドに2つのプロミスを渡します。
Promise.race([getData()
.then(showContent)
.then(hideLoadingIndicator), timeout()
])
.catch(showLoadingIndicator);
Code language: JavaScript (javascript)
最初のプロミスは、サーバーからデータを取得し、コンテンツを表示し、ロードインジケーターを非表示にします。2つ目のプロミスは、タイムアウトを設定します。
最初のプロミスが解決するのに 500 ms 以上かかると、ロードインジケーターを表示するために catch()
が呼び出されます。最初のプロミスが解決されると、ロードインジケーターが非表示になります。
最後に、ボタンを 2 回目クリックした場合にメッセージとロードインジケーターを非表示にする reset()
関数を開発します。
// reset UI
function reset() {
hideLoadingIndicator();
showContent('');
}
Code language: JavaScript (javascript)
すべてまとめて配置してください。
// after 0.5 seconds, if the getData() has not resolved, then show
// the Loading indicator
const TIMEOUT = 500;
const DATA_LOAD_TIME = 5000;
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const message = 'Promise.race() Demo';
resolve(message);
}, DATA_LOAD_TIME);
});
}
function showContent(message) {
document.querySelector('#message').textContent = message;
}
function timeout() {
return new Promise((resolve, reject) => {
setTimeout(() => reject(), TIMEOUT);
});
}
function showLoadingIndicator() {
document.querySelector('#loader').className = 'loader';
}
function hideLoadingIndicator() {
document.querySelector('#loader').className = '';
}
// handle button click event
const btn = document.querySelector('#btnGet');
btn.addEventListener('click', () => {
// reset UI if users click the second time
reset();
// show content or loading indicator
Promise.race([getData()
.then(showContent)
.then(hideLoadingIndicator), timeout()
])
.catch(showLoadingIndicator);
});
// reset UI
function reset() {
hideLoadingIndicator();
showContent('');
}
Code language: JavaScript (javascript)
まとめ
Promise.race(iterable)
メソッドは、イテラブル内のプロミスのいずれかが解決または拒否されるとすぐに、その値またはエラーを使用して、解決または拒否する新しいプロミスを返します。