如何在 JavaScript 中使用 then 和 catch 与 Promise 配合使用 finally?
Javascript 异步编程使用 Promise 对象,它不会阻塞当前流程的执行,而是通知编译器尚有一些未完成的任务,并在任务完成后向系统返回信号。主要有两种可能性:Promise 对象要么成功完成,要么通过返回异常停止。为了处理来自 Promise 对象的异常,使用 catch() 方法。在 try-catch 方法中,我们还可以使用另一个名为“finally”的块。无论之前做了什么,它都会执行。对于 Promise,我们也可以使用 finally() 函数来实现相同的功能。因此,在本文中,我们的最终目标是了解如何在 Promise 中使用 then() 和 catch() JavaScript 方法与 finally 配合使用。
基本语法如下:
语法
promise
.then(
// do something with the result
result => { ...}
)
.catch(
// handle error
error => { ... }
)
.finally(
// do something when it has been executed successfully
// or raised an error.
// this work can be memory cleaning or similar task
() => { ... }
)
无论 Promise 是 fulfilled 还是 rejected,finally() 方法始终都会执行。换句话说,当调用 finally() 方法时,Promise 就会被 settled。finally() 函数在 ES2018 中首次出现。可以在 finally() 方法中放置在 Promise fulfilled 时销毁资源的代码,无论其结果如何。如果不使用 finally() 方法,我们需要在 then() 和 catch() 方法中清除我们的资源。
不使用 Finally
promise
.then(
// do something with the result
result => { ...}
// do something to clear resources
)
.catch(
// handle error
error => { ... }
// do something to clear resources
)
then() 和 catch() 块包含重复的代码。通过添加 finally() 块,可以轻松避免这种重复。try...catch...finally 语句中的“finally”块与 finally() 函数是相关的构造。对于同步编程中的资源清理,请使用“finally”块。而 finally() 方法则用于异步程序。
让我们来看一个示例,其中我们创建一个“Connection”类来创建数据库连接(假设)。有两种不同的方法:run() 方法用于执行查询,另一个名为 terminate() 的方法用于终止连接并清理资源。连接类定义如下:
连接类
class Connection {
run( query ) {
if (query != 'Add' && query != 'Modify' && query != 'Remove') {
throw new Error( `Invalid query: ${query}`);
}
console.log(`Running given query: ${query}`);
return this;
}
terminate() {
console.log( 'Terminating already connected connection' )
}
}
然后我们定义一个 connect() 方法,该方法将创建一个连接对象并返回一个 Promise 对象来处理连接。当它完成操作时,会返回一个新的连接对象,否则会引发错误。让我们看看函数定义以清楚地理解。
Connect 方法
class Connection {
run( query ) {
if (query != 'Add' && query != 'Modify' && query != 'Remove') {
throw new Error( `Invalid query: ${query}`);
}
console.log(`Running given query: ${query}`);
return this;
}
terminate() {
console.log( 'Terminating already connected connection' )
}
}
在最后处理场景时,使用 finally() 块。在下面的示例中:因为 success 标志设置为 true,所以 connect() 函数解析为一个新的 Connection 对象。第一个 then() 方法通过执行 Insert 查询来执行,它也返回一个 Connection 对象。连接通过 globalConnection 保存。第二个 then() 方法执行 Select 查询,它也会抛出一个错误。finally() 方法终止连接,而 catch() 方法显示错误消息。
finally 方法的使用
let globalConnection;
connect()
.then( (connection) => {
globalConnection = connection;
return globalConnection.run( 'Add' );
})
.then( (connection) => {
globalConnection = connection;
return globalConnection.run( 'Remove' );
})
.then((connection) => {
globalConnection = connection;
return connection.run( 'Union' );
})
.catch( console.log )
.finally( () => {
if ( globalConnection ) {
globalConnection.terminate();
}
});
完整的代码和相应的输出如下:
源代码
class Connection {
run( query ) {
if (query != 'Add' && query != 'Modify' && query != 'Remove') {
throw new Error( `Invalid query: ${query}`);
}
console.log(`Running given query: ${query}`);
return this;
}
terminate() {
console.log( 'Terminating already connected connection' )
}
}
const success = true;
function connect() {
return new Promise( (resolve, reject) => {
if ( success )
resolve( new Connection() );
else
reject( 'Connection cannot be created' );
});
}
let globalConnection;
connect()
.then( (connection) => {
globalConnection = connection;
return globalConnection.run( 'Add' );
})
.then( (connection) => {
globalConnection = connection;
return globalConnection.run( 'Remove' );
})
.then((connection) => {
globalConnection = connection;
return connection.run( 'Union' );
})
.catch( console.log )
.finally( () => {
if ( globalConnection ) {
globalConnection.terminate();
}
});
输出
Running given query: Add
Running given query: Remove
Error: Invalid query: Union
at Connection.run (/home/cg/root/18775/main.js:4:16)
at /home/cg/root/18775/main.js:36:25
Terminating already connected connection
使用 finally() 方法来 settled Promise,这会导致一个函数在 Promise fulfilled 或 rejected 时运行。无论 Promise 的结果如何,最好将清理资源的代码放在 finally() 方法中。
结论
在构建和分发系统到另一个平台或构建可用的平台时,异常处理是一项至关重要的任务。异常处理使用 try-catch 块。catch 块的目的是使用已建立的逻辑来处理异常。我们与它们一起使用的另一个块是我们称之为“finally”的块,无论是否发生异常,它都会执行。但只有同步系统应该使用此过程。在异步编程中,由于延迟响应,错误可能会稍后出现。为了管理异常,我们可以使用 then() 方法,它类似于 try 块。但是,在这种情况下,我们使用 finally() 函数来获得与“finally”块相同的结果。无论 Promise 是成功执行还是出现错误,此函数通常用于执行清理操作。
数据结构
网络
关系型数据库管理系统
操作系统
Java
iOS
HTML
CSS
Android
Python
C 编程
C++
C#
MongoDB
MySQL
Javascript
PHP