概要: このチュートリアルでは、JavaScript Promise の finally()
メソッドを使用して、Promise の結果に関わらず、Promise が確定した後にコードを実行する方法を学びます。
JavaScript Promise finally() メソッドの紹介
Promise インスタンスの finally()
メソッドを使用すると、Promise が確定したときに実行される関数をスケジュールできます。
finally()
メソッドの呼び出し方は次のとおりです。
promise.finally(onFinally)
Code language: JavaScript (javascript)
この構文では
onFinally
は、Promise が確定したときに非同期的に実行される関数です。
finally() メソッドは Promise オブジェクトを返し、Promise インスタンスの他のメソッドへの呼び出しを便利にチェーンできます。
finally()
メソッドは ES2018 で導入されました。finally()
メソッドを使用すると、Promise の結果に関わらず、Promise が確定したときにリソースをクリーンアップするコードを配置できます。
finally()
メソッドを使用することで、次のように then()
および catch()
メソッドで重複したコードを避けることができます。
promise
.then(result => {
// process the result
// clean up the resources
})
.catch(error => {
// handle the error
// clean up the resources
});
Code language: JavaScript (javascript)
これで、リソースのクリーンアップ部分を次のように finally()
メソッドに移動できます。
promise
.then(result => {
// process the result
})
.catch(error => {
// handle the error
})
.finally(() => {
// clean up the resources
});
Code language: JavaScript (javascript)
finally()
メソッドは、try...catch...finally
ステートメントの finally
ブロックに似ています。
同期コードでは、リソースをクリーンアップするために finally
ブロックを使用します。非同期コードでは、代わりに finally()
メソッドを使用します。
JavaScript Promise finally() メソッドの例
Promise の finally()
メソッドの使用例をいくつか見てみましょう。
1) リソースをクリーンアップするための finally() メソッドの使用
以下は、Connection
クラスの定義です。
class Connection {
execute(query) {
if (query != 'Insert' && query != 'Update' && query != 'Delete') {
throw new Error(`The ${query} is not supported`);
}
console.log(`Execute the ${query}`);
return this;
}
close() {
console.log('Close the connection')
}
}
Code language: JavaScript (javascript)
Connection
クラスには、execute()
と close()
の 2 つのメソッドがあります。
execute()
メソッドは、insert、update、または delete クエリのみを実行します。リストにない別のクエリを渡すとエラーが発生します。close()
メソッドは接続を閉じ、リソースをクリーンアップします。
次の connect()
関数は、成功フラグが true に設定されている場合に、新しい Connection
に解決される Promise を返します。
const success = true;
function connect() {
return new Promise((resolve, reject) => {
if (success)
resolve(new Connection());
else
reject('Could not open the database connection');
});
}
Code language: JavaScript (javascript)
次の例では、finally()
メソッドを使用して接続を閉じます。
let globalConnection;
connect()
.then((connection) => {
globalConnection = connection;
return globalConnection.execute('Insert');
})
.then((connection) => {
globalConnection = connection;
return connection.execute('Select');
})
.catch(console.log)
.finally(() => {
if (globalConnection) {
globalConnection.`close()`;
}
});
Code language: JavaScript (javascript)
この例では
success
フラグがtrue
に設定されているため、connect()
関数は新しいConnection
オブジェクトに解決されます。- 最初の
then()
メソッドはInsert
クエリを実行し、Connection
オブジェクトを返します。globalConnection
は接続を保存するために使用されます。 - 2番目の
then()
メソッドはSelect
クエリを実行し、エラーを発行します。catch()
メソッドはエラーメッセージを表示し、finally()
メソッドは接続を閉じます。
2) Promsie finally() メソッドを使用して読み込みステータスを表示する
次の例では、パブリック API https://jsonplaceholder.typicode.com/posts を呼び出した後、finally()
メソッドを使用して読み込み要素を非表示にする方法を示します。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript finally - API Call with Loading State</title>
<script src="app.js" defer></script>
</head>
<body>
<button id="fetchButton">Fetch Data</button>
<div id="loading" style="display: none">Loading...</div>
<div id="content" style="display: none"></div>
</body>
</html>
Code language: JavaScript (javascript)
app.js
document.getElementById('fetchButton').addEventListener('click', () => {
const loadingElement = document.getElementById('loading');
const contentElement = document.getElementById('content');
// Show loading and hide content
loadingElement.style.display = 'block';
contentElement.style.display = 'none';
// Make the API call to get posts
fetch('https://jsonplaceholder.typicode.com/posts')
.then((response) => response.json())
.then((posts) => {
// Render the posts
const renderedPosts = posts
.map((post) => {
return `
<h1>${post.title}</h1>
<p>${post.body}</p>
`;
})
.join('');
// Show the posts
contentElement.innerHTML = renderedPosts;
})
.catch((error) => {
// Handle any errors
contentElement.innerHTML = `<p>Failed to load data</p>`;
})
.finally(() => {
// Hide loading and show content
loadingElement.style.display = 'none';
contentElement.style.display = 'block';
});
});
Code language: JavaScript (javascript)
仕組み。
まず、ボタンにクリックイベントハンドラーを追加します。
document.getElementById('fetchButton').addEventListener('click', () => {
// ...
});
Code language: JavaScript (javascript)
次に、読み込み要素を表示し、コンテンツ要素を非表示にします。
const loadingElement = document.getElementById('loading');
const contentElement = document.getElementById('content');
// Show loading and hide content
loadingElement.style.display = 'block';
contentElement.style.display = 'none';
Code language: JavaScript (javascript)
3番目に、Fetch API を使用して API を呼び出し、投稿をレンダリングします。
fetch('https://jsonplaceholder.typicode.com/posts')
.then((response) => response.json())
.then((posts) => {
// Render the posts
const reenderedPosts = posts
.map((post) => {
return `
<h1>${post.title}</h1>
<p>${post.body}</p>
`;
})
.join('');
// Show the posts
contentElement.innerHTML = reenderedPosts;
})
.catch((error) => {
// Handle any errors
contentElement.innerHTML = `<p>Failed to load data</p>`;
})
.finally(() => {
// Hide loading and show content
loadingElement.style.display = 'none';
contentElement.style.display = 'block';
});
Code language: JavaScript (javascript)
finally()
メソッドでは、読み込み要素を非表示にし、コンテンツ要素を表示します。
まとめ
finally()
メソッドは、Promise が満たされたか拒否されたかに関わらず、Promise が確定したときに実行される関数をスケジュールします。- Promise が確定したら、結果に関わらずリソースをクリーンアップするコードを
finally()
メソッドに配置するのが良い習慣です。