如何在 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