簡體   English   中英

手柄 Promise 卡入 Typescript

[英]Handle Promise Catches in Typescript

我有一個基於 promise 的 API 服務,它從我的后端請求數據。 它還帶有自己的錯誤捕獲,所以我不必到處寫它。 當它這樣寫時:

后端服務.ts

...
getTasks() {
    return axios.get('/api/tasks')
        .then((response) => {
            const {
                tasks
            }: {
                tasks: tasksType
            } = response.data;
            return tasks;
        })
        .catch((error) => console.log(error));
}
...

條目.tsx

...
const getTasks = () => {
    backendService.getTasks()
        .then((tasks: tasksType) => {
            const filteredTasksData = filterAPIDataForState(tasks);

            addTasks({
                tasks: filteredTasksData
            });
        })
}
...

我收到以下錯誤:

TS2345: Argument of type '(tasks: tasksType) => void'
is not assignable to parameter of type '(value: void | tasksType) => void | PromiseLike<void>'.Types of parameters 'tasks'
and 'value'
are incompatible.Type 'void | tasksType'
is not assignable to type 'tasksType'.Type 'void'
is not assignable to type 'TaskInterface[]'.

我想這是因為捕獲,這可能會使 Promise 什么都不返回(因為 console.log)。 如果我從Entries.tsxgetTasks它自己的 catch 處理程序並將其從 BackendService.ts getTasks中刪除,它就可以工作。

如果出現錯誤,Typescript 是否應該能夠判斷Entries.tsx中的 .then .then()不會運行,因為已經有處理這種情況的捕獲?

如果出現錯誤,Entries.tsx 中的 the.then() 將不會運行,因為已經有一個 catch 處理這種情況?

這並不完全正確。

backendService.ts文件中getTasks方法中的catch塊返回undefinedcatch塊返回一個值而不是拋出捕獲的錯誤時,而不是調用調用代碼的catch塊, then調用塊

發生這種情況是因為Promise文件中getTasks方法返回的backendService.ts取決於以下內容:

  • 如果Promise axios.get(...)返回的 Promise 滿足,那么您在then(...)塊中執行的操作

  • 如果Promise axios.get(...)返回的 Promise 被拒絕,那么您在catch(...)塊中執行的操作

在您的情況下,如果Promise axios.get(...)滿足,則then(...)塊將執行,並且由於它只返回tasksPromise中的getTasks方法backendService.ts文件。在調用代碼中調用then(...)塊,即在Entries.tsx文件中。

如果Promise axios.get(...)返回的 Promise 被拒絕,則將執行catch(...)塊。 由於getTasks方法中的catch(...)塊只是記錄錯誤, Promise方法返回的getTasks滿足undefined的值,這將導致調用代碼中then(...)塊的調用,即在Entries.tsx文件。

請參閱以下示例以了解這一點。

 function getData() { // incorrect url which will lead to response.ok being false const url = 'https://jsonplaceholder.typicode.com/todo/1'; return fetch(url).then(response => { if (response.ok) { return response.json(); } else { throw new Error(); } }).catch(error => console.log('catch block in getData function')); } getData().then(data => console.log('then block ran')).catch(error => console.log('error block ran'));

在上面的代碼片段中,由於 API URL 不正確, then塊中的response.ok為 false,因此從then塊中拋出錯誤,該塊被同一 ZC1C425268E68385D1AB5074C 中的catch塊捕獲。 由於這個catch塊只是記錄一條消息並返回undefined ,因此getData Promise返回的 Promise 滿足undefined的值。 因此,代替catch塊, then塊在調用getData function 的代碼中執行。

如果您不知道這一點,那么您可能會驚訝地看到這種行為,但這就是Promisescatch塊一起工作的方式。 這種行為的原因是,如果您的 promise 鏈具有多個catch塊,如下所示:

fetch(...)
  .then(...)
  .catch(...)   
  .then(...)
  .then(...)
  .catch(...);

然后,如果第一個catch塊捕獲到任何鏈接在它之前的函數拋出的錯誤,那么這個catch塊可以做以下兩件事之一:

  • 拋出錯誤,然后將導致調用最后一個catch
  • 處理錯誤並返回一些值

如果第一個catch塊正常返回,則catch塊返回的 promise 滿足該catch塊的返回值,然后該值成為 ZB321DE3BDC299EC807E9F795D7 鏈中下一個then塊的回調 function 的輸入。 因此,promise 鏈會繼續,而不是在第一個catch塊執行后立即停止。


回到您的代碼,當catch塊在backendService.ts文件中的getTasks方法中執行時,它會記錄消息並返回undefined ,然后導致調用Entries.tsx文件中的then塊,而不是catch塊和這就是為什么您會收到 typescript 關於您的代碼的投訴。

解決方案

您可以使用以下選項之一來解決此問題:

  • 拋出在backendService.ts文件中getTasks方法的catch(...)塊中捕獲的錯誤,以便Promise方法返回的getTasks被拒絕,而不是用undefined的值完成。

  • 刪除backendService.ts文件中getTasks function 中的catch塊,並在調用getTasks方法的代碼中添加catch塊。

在我看來,在backendService.ts文件中不需要catch塊,因為如果Promise axios.get(...)返回的getTasks被拒絕, Promise返回catch方法也會被拒絕。 getTasks方法。 因此,只需從getTasks方法中刪除catch(...)塊,然后在調用此getTasks方法的位置添加catch(...)塊。

有很多選項可以處理這個

  1. 在 BackendService.getTasks() 中只需 remove.catch() 和 handle.catch() 在 Entries.getTasks()
  2. 在 BackendService.getTasks() 添加另一個 then 並返回空任務,例如 example.then(it => it || [])

Axios 在響應錯誤時不會崩潰,因此您必須正確檢查響應並處理它,因為它不應該只是盲目地破壞響應 object

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM