我有一个基于诺言的API服务,该服务从后端请求数据。它还带有它自己的错误捕获,因此我不必到处编写它。这样写的时候:
BackendService.ts
...
getTasks() {
return axios.get('/api/tasks')
.then((response) => {
const {
tasks
}: {
tasks: tasksType
} = response.data;
return tasks;
})
.catch((error) => console.log(error));
}
...
Entries.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)。如果我将getTasks
中的Entries.tsx
设为自己的捕获处理程序,并将其从BackendService.ts getTasks
中删除,它将起作用。
Typescript是否不能告诉.then()
中的Entries.tsx
如果发生错误就不会运行,因为已经有一个捕获来处理这种情况了?
答案 0 :(得分:2)
如果出现错误,Entries.tsx中的.then()将不会运行,因为 已经有处理这种情况的陷阱了?
那不是完全正确。
catch
文件中getTasks
方法中的 backendService.ts
块返回undefined
,而当catch
块返回值时引发捕获的错误,而不是调用调用代码的catch
块,而是调用 then
块。
之所以会这样,是因为Promise
文件中的getTasks
方法返回的backendService.ts
取决于以下内容:
如果Promise
返回的axios.get(...)
完成了,那么您在then(...)
块中所做的事情
如果Promise
返回的axios.get(...)
被拒绝,那么您在catch(...)
块中所做的事情
在您的情况下,如果Promise
个实现返回的axios.get(...)
,则将执行then(...)
块,因为它只返回了tasks
,所以返回了Promise
通过getTasks
文件中的backendService.ts
方法实现,导致在调用代码即then(...)
文件中调用Entries.tsx
块。
如果Promise
返回的axios.get(...)
被拒绝,则将执行catch(...)
块。由于catch(...)
方法中的getTasks
块仅记录了错误,因此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不正确,response.ok
块中的then
为false,因此从then
块中抛出了错误,{ {1}}块在同一函数中。由于此catch
块仅记录一条消息并返回catch
,因此undefined
函数返回的Promise
的值为getData
。因此,undefined
块不是catch
块,而是在调用then
函数的代码中执行。
如果您不知道这一点,那么您可能会惊讶地看到这种行为,但这就是getData
与Promises
块一起工作的方式。这种现象的原因是
如果您的诺言链包含多个catch
块,如下所示:
catch
然后,如果第一个fetch(...)
.then(...)
.catch(...)
.then(...)
.then(...)
.catch(...);
块捕获到从它之前链接的任何函数引发的错误,则此catch
块可以执行以下两项操作之一:
catch
块的调用如果第一个catch
块正常返回,则catch
块返回的承诺将以catch
块的返回值实现,然后该值成为回调函数的输入。承诺链中的下一个catch
块。因此,承诺链会继续执行,而不是在第一个then
块执行后立即停止。
回到您的代码,当在catch
文件中的catch
方法中执行getTasks
块时,它将记录该消息并返回backendService.ts
,然后导致调用undefined
文件中的then
块,而不是Entries.tsx
块,这就是为什么打字稿会抱怨您的代码的原因。
解决方案
您可以使用以下选项之一来解决此问题:
将在catch
文件的catch(...)
方法的getTasks
块的backendService.ts
块中引发的错误扔给Promise
方法返回的getTasks
满足undefined
的价值。
在catch
文件的getTasks
函数中删除backendService.ts
块,并在调用catch
方法的代码中添加getTasks
块。
我认为catch
文件中不需要backendService.ts
块,因为如果Promise
返回的axios.get(...)
被拒绝,则返回Promise
如果getTasks
方法中没有catch
块,则getTasks
的by by方法也会被拒绝。因此,只需从catch(...)
方法中删除getTasks
块,并在调用此catch(...)
方法的位置添加getTasks
块。
答案 1 :(得分:0)
有很多方法可以解决这个问题
当响应错误时,Axios不会崩溃,因此您必须正确检查并处理响应,因为它不只是盲目地破坏响应对象