@catch 指令
@catch
指令可以加到 Relay 查詢/片段/變異中的欄位,以宣告在執行時應如何處理例外狀況和非預期的值。使用 @catch
可讓 Relay 在回應資料中提供您例外狀況,而不是預設行為的 null 值。
當 GraphQL 回應包含欄位錯誤時 - Relay 會尋找錯誤,如果該欄位或父欄位存在 @catch
指令,則會以 {ok: true, value: "您的值"}
或 {ok: false, errors: [...]}
回應。
如果 @catch
錯誤直接在錯誤來源的欄位上捕獲 - 則會在該欄位上提供錯誤。以下是一個範例
query MyQuery {
viewer {
name @catch
age
}
}
如果 name
包含錯誤 - 它將在回應資料中的 name
欄位上提供 - 如下所示
{
viewer: {
name: {
ok: false,
errors: [
{
message: "Couldn't get name",
path: ['viewer', 'name']
}
]
}
age: 39
}
}
但是,如果 @catch
存在於欄位的祖先之一,則該錯誤將會向上冒泡到那裡,如下所示
query MyQuery {
viewer @catch {
name
age
}
}
{
viewer: {
ok: false,
errors: [
{
message: "Couldn't get name",
path: ['viewer', 'name']
}
]
}
}
@catch
可以捕獲什麼?
酬載錯誤
酬載錯誤是在執行給定欄位回應時,由於伺服器端例外狀況而發生的錯誤。在這種情況下,GraphQL 伺服器會在應該有值的地方提供 null 值,並提供一個獨立的 errors 物件。
當您在欄位上使用 @catch
時,Relay 會取得這些錯誤並將其內嵌提供給您,使其更易於處理,且不再是隱藏的。
另一個很棒的副作用是,如果欄位是可為 null 的,您現在將知道 null 是例外狀況的結果還是真正的 null - 因為形狀將包含 {ok: true}
與值 null
,或 {ok: false}
與實際錯誤。
@catch 下的 @required(action: THROW)
如果您的 @required(action: THROW)
的祖先包含 @catch
- @required
錯誤不會拋出例外狀況,而是會向上冒泡,並以與一般錯誤相同的方式提供。以下是一個範例
query MyQuery {
viewer @catch {
name @required(action: THROW)
age
}
}
{
viewer: {
ok: false,
errors: [
{
message: "Relay: Missing @required value at path 'viewer.name' in 'MyQuery'.",
}
]
}
}
回應中遺失的資料
如果預期欄位具有值,但該欄位未定義 - 則該欄位被視為「遺失資料」。這也是非預期的狀態 - 當它發生在具有 @catch
作為祖先時,也會被捕獲,如下所示
{
viewer: {
ok: false,
errors: [
{
message: "Relay: Missing data for one or more fields in MyQuery",
}
]
}
}
@catch
如何與 @throwOnFieldError
互動?
使用 @throwOnFieldError
可讓欄位在發生欄位錯誤時拋出 JavaScript 例外狀況。透過使用 @catch
- 您告訴 Relay 在這種情況下您不想要 JavaScript 例外狀況。相反地,您要求錯誤以資料物件的形式提供,其行為和規則與上述所列相同(包括冒泡到父欄位)。
重要的是要注意,您仍然可以在沒有 @throwOnFieldError
的情況下使用 @catch
。它仍然會在資料物件中提供您錯誤。但是,其他不在 @catch
下的欄位仍然不會拋出 - 因為會缺少 @throwOnFieldError
。
在此處深入了解 @throwOnFieldError
。
@catch
引數
to: RESULT(預設)
@catch(to: RESULT)
會啟用上述行為 - 對於包含錯誤的相同或子欄位,內嵌提供錯誤。這是預設引數 - 這表示您可以寫入 @catch
或 @catch(to: RESULT)
,行為將會相同。
to: NULL
@catch(to: NULL)
將為您提供與 @catch
啟用之前完全相同的行為。如果欄位包含錯誤,則該欄位將為 null。