摘要:在本教程中,您将学习如何使用 JavaScript Promise finally()
方法在 Promise 解决后执行代码,无论其结果如何。
JavaScript Promise finally() 方法介绍
finally()
方法是 Promise 实例的方法,允许您安排一个函数在 Promise 解决时执行。
以下是调用 finally()
方法的语法
promise.finally(onFinally)
Code language: JavaScript (javascript)
在此语法中
onFinally
是一个函数,当 Promise 解决时异步执行。
finally() 方法返回一个 Promise 对象,允许您方便地将调用链接到 Promise 实例的其他方法。
finally()
方法在 ES2018 中引入。使用 finally()
方法,您可以放置 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()
execute()
方法只执行插入、更新或删除查询。如果您传入不在列表中的其他查询,它将发出错误。close()
方法关闭连接并清理资源。
以下 connect()
函数返回一个 Promise,如果成功标志设置为 true,则解析为新的 Connection
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)
在此示例中
connect()
函数解析为新的Connection
对象,因为success
标志设置为true
。- 第一个
then()
方法执行Insert
查询并返回Connection
对象。globalConnection
用于保存连接。 - 第二个
then()
方法执行Select
查询并发出错误。catch()
方法显示错误消息,finally()
方法关闭连接。
2) 使用 Promsie finally() 方法显示加载状态
以下示例展示了如何使用 finally()
方法在调用公共 API https://jsonplaceholder.typicode.com/posts 后隐藏加载元素。
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)
第三,使用 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 解决后将清理资源的代码放在
finally()
方法中,无论其结果如何。