在读取错误集状态内提取



我在解决这个反应时遇到了问题.js

loadFromServer(pageSize) {
fetch('http://localhost:8080/api/employees')
.then(response => {
return fetch('http://localhost:8080/api/profile/employees',
{
headers: new Headers({
'Accept': 'application/schema+json'
})
}).then(schema => {
this.scheme =  schema;
return response.json();
}   
)
})
.then(response =>             
this.setState(
{
employees: response._embedded.employees,
attributes: Object.keys(this.scheme.json().properties),
pageSize: pageSize,
links: response._links}                      
)
);          
}

在这一部分

attributes: Object.keys(this.scheme.json().properties),

始终返回(承诺(TypeError: Cannot convert undefined or null to object.

如果我放console.log(this.scheme.json())我可以看到承诺,但是,为什么在里面setState我得到空对象?

这里有几个问题:

  • 最主要的是this.schema.json()返回一个承诺(正如您从console.log中知道的那样(。承诺没有properties属性,因此您将undefined传递给Object.keys,然后会给您该错误。
  • 你也没有以两种不同的方式检查来自fetch的错误:你没有检查.ok(这是我在贫乏的小博客上发布的一个常见错误(,你没有检查承诺拒绝。

您还在做一些不必要的承诺嵌套,并且可能会更多地重叠您的fetch调用。

首先,由于您似乎经常获取 JSON,我建议为自己提供一个实用程序函数:

function fetchJSON(...args) {
return fetch(...args)
.then(response => {
if (!response.ok) {
throw new Error('HTTP error ' + response.status);
}
return response.json();
});
}

请注意.ok检查。

然后,同样在"将问题分解为更小的部分"类别中,我将有一个fetchSchema函数:

function fetchSchema(url) {
return fetchJSON(url, {
headers: new Headers({
'Accept': 'application/schema+json'
})
});
}

然后,loadFromServer可以使用Promise.all和解构来并行运行操作:

// (I assume this is in a `class` or object initializer, as it doesn't have `function` in front of it)
loadFromServer(pageSize) {
Promise.all(
fetchJSON('http://localhost:8080/api/employees'),
fetchSchema('http://localhost:8080/api/profile/employees')
)
.then(([empResponse, schema]) => {
this.schema = schema;
this.setState({
employees: empResponse._embedded.employees,
attributes: Object.keys(schema.properties),
pageSize: pageSize,
links: empResponse._links
})
)
.catch(error => {
// Do something with the error
});
}

请注意.catch,因为您不会从loadFromServer返回承诺。(如果要将错误反转到链上,请在Promise.all前面添加return,并将.catch移动到调用代码。


旁注:您的代码已使用

this.scheme =  schema;

请注意,左侧的属性是scheme的(带有最终e(,但变量是schema的(带有最终a(。我想你的意思是schema所以我在上面包含了这个变化,但如果属性真的应该this.scheme,你会想要调整它。或者,如果您不需要该属性来处理loadFromServer中的代码以外的任何内容,请完全删除该行。

我认为您应该使用Promise.all在 parrallel 中运行两个请求,然后检索两个响应(顺便说一下response.json()返回一个Promise,这就是您的代码中有错误的原因(:

loadFromServer(pageSize) {
Promise.all([
fetch('http://localhost:8080/api/employees')
.then(response => {
if (!response.ok) throw Error(response.statusText);
return response.json();
),
fetch('http://localhost:8080/api/profile/employees')
.then(response => {
if (!response.ok) throw Error(response.statusText);
return response.json();
),
]).then(responses => {
this.setState({
employees: responses[0]._embedded.employees,
attributes: Object.keys(responses[1].properties),
pageSize: pageSize,
links: responses[0]._links
})
}).catch(error => {...})        
}

我认为你需要这样的东西:

loadFromServer(pageSize) {
fetch('http://localhost:8080/api/employees')
.then(response => {
return fetch('http://localhost:8080/api/profile/employees', {
headers: new Headers({
'Accept': 'application/schema+json'
})
}).then(schema => {
schema.json().then(data => {
this.scheme = data
})
});
return response.json();
})
.then(response =>
this.setState({
employees: response._embedded.employees,
attributes: Object.keys(this.scheme.properties),
pageSize: pageSize,
links: response._links
})
);
}

Fetch API 中的响应json()方法返回一个承诺。因此,fetch请求应始终与.then(response => response.json())链接,以获取普通对象。

扁平化承诺可能会产生更可靠的控制流。由于使用了来自两个请求的响应,因此这需要嵌套then回调或通过链传递另一个响应thenasync可能很有用,因为它可以方便地解决扁平化问题:

async loadFromServer(pageSize) {
const employeesResponse = await fetch('http://localhost:8080/api/employees', {
headers: new Headers({ 'Accept': 'application/schema+json' })
});
const employees = await employeesResponse.json();
const schemeResponse = await fetch('http://localhost:8080/api/profile/employees', {
headers: new Headers({ 'Accept': 'application/schema+json' })
});
const scheme = await schemeResponse.json();
this.setState({
employees: employees._embedded.employees,
attributes: Object.keys(scheme.properties),
pageSize: pageSize,
links: response._links
});
}

由于请求不相互依赖,因此它们可以与Promise.all并行执行。

async loadFromServer(pageSize) {
const employeesPromise = fetch('http://localhost:8080/api/employees', {
headers: new Headers({ 'Accept': 'application/schema+json' })
})
.then(res => res.json());
const schemePromise = fetch('http://localhost:8080/api/profile/employees', {
headers: new Headers({ 'Accept': 'application/schema+json' })
})
.then(res => res.json());
const [employees, scheme] = await Promise.all([employeesPromise, schemePromise]);
this.setState({
employees: employees._embedded.employees,
attributes: Object.keys(scheme.properties),
pageSize: pageSize,
links: response._links
});
}

最新更新