如何处理这个 fetch() TypeError?
How to handle this fetch() TypeError?
我正在尝试将我的提取查询的响应状态打印到控制台(以便稍后处理这些边缘情况)。但是,唯一有效的 console.log 调用是 'breaches' 函数中的调用。当 HIBP 数据库中存在帐户时,我没有收到任何错误,但当帐户不在数据库中时,我收到 'Request failed: TypeError: response.json is not a function at json' 错误。我究竟做错了什么?我从 Google Web Dev 篇文章中得到了错误处理代码。
function createNode(element) {
return document.createElement(element);
}
function append(parent, el) {
return parent.appendChild(el);
}
function status(response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
console.log('all is good');
} else if (response.status == 404) {
return Promise.resolve(response.statusText)
console.log('no breaches');
} else if (response.status == 400) {
return Promise.resolve(response.statusText)
console.log('bad req');
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json(response) {
return response.json()
}
var account = document.getElementById('account'),
results = document.getElementById('results');
account.addEventListener("keyup", keyupEvent);
function keyupEvent() {
event.preventDefault();
if (event.key === "Enter") {
fetch('https://haveibeenpwned.com/api/v2/breachedaccount/' + account.value, {
timeout: 1500,
userAgent: 'test'
})
.then(status)
.then(json)
.then(function(breaches) {
console.log('Status Code: ' + breaches.status);
let span = createNode('span');
return breaches.forEach(function(check) {
span.innerHTML = `${check.Name}<br/>`;
append(results, span)
})
}).catch(function(error) {
console.log('Request failed:', error);
});
}
}
您的 status
函数 returns(承诺)状态 text 用于 400s 或 404s 的响应。您使用 fetch
结果的承诺链无法处理这种可能性;它假定它获得了响应对象。
您可能希望在 400 或 404 上拒绝而不是解决,但如果不是,您需要在 then
处理程序中分支以期望读取 JSON。
您使用漏洞的代码也在覆盖相同的 span
并重复附加它;它最终只会附加一次 last 违规信息。 append
函数并没有提供任何有用的抽象,只是调用 appendChild
.
如果 API 真的 returns 404 for "no breaches" (blech),那么我会去掉 createNode
和 append
,改变status
到此:
function status(response) {
if (response.ok) {
return response.json();
} else if (response.status === 404) { // If the API *really* returns
return []; // a 404 for "no breaches"
} else {
throw new Error(response.statusText);
}
}
然后:
fetch('https://haveibeenpwned.com/api/v2/breachedaccount/' + account.value, {
timeout: 1500,
userAgent: 'test'
})
.then(status)
.then(breaches => {
// No `return` here, the chain isn't passed on and there
// aren't any further resolution handlers
breaches.forEach(check => { // Or a for-of loop
const span = document.createElement("span");
span.innerHTML = `${check.Name}<br/>`;
results.appendChild(span);
});
}).catch(error => {
console.log('Request failed:', error);
});
另外:您的 status
函数表明您没有意识到 then
(和 catch
)创建新的承诺。如果您的 status
函数仅用作 then
处理程序,则没有理由创建任何承诺。它应该只是一个 return 值(由 then
创建的承诺将使用该值解析)或抛出错误(由 then
创建的承诺将拒绝该错误):
// This is equivalent to your current `status` function (assuming it's always
// used as a `then` callback)
function status(response) {
if (response.ok) { // if (response.status >= 200 && response.status < 300) {
// all okay
return response;
} else if (response.status == 404) {
// no breaches
return response.statusText;
} else if (response.status == 400) {
// bad request
return response.statusText;
} else {
throw new Error(response.statusText);
}
}
(我删除了每个分支中 return
之后 的 console.log
行,因为它们无法访问。)
我正在尝试将我的提取查询的响应状态打印到控制台(以便稍后处理这些边缘情况)。但是,唯一有效的 console.log 调用是 'breaches' 函数中的调用。当 HIBP 数据库中存在帐户时,我没有收到任何错误,但当帐户不在数据库中时,我收到 'Request failed: TypeError: response.json is not a function at json' 错误。我究竟做错了什么?我从 Google Web Dev 篇文章中得到了错误处理代码。
function createNode(element) {
return document.createElement(element);
}
function append(parent, el) {
return parent.appendChild(el);
}
function status(response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
console.log('all is good');
} else if (response.status == 404) {
return Promise.resolve(response.statusText)
console.log('no breaches');
} else if (response.status == 400) {
return Promise.resolve(response.statusText)
console.log('bad req');
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json(response) {
return response.json()
}
var account = document.getElementById('account'),
results = document.getElementById('results');
account.addEventListener("keyup", keyupEvent);
function keyupEvent() {
event.preventDefault();
if (event.key === "Enter") {
fetch('https://haveibeenpwned.com/api/v2/breachedaccount/' + account.value, {
timeout: 1500,
userAgent: 'test'
})
.then(status)
.then(json)
.then(function(breaches) {
console.log('Status Code: ' + breaches.status);
let span = createNode('span');
return breaches.forEach(function(check) {
span.innerHTML = `${check.Name}<br/>`;
append(results, span)
})
}).catch(function(error) {
console.log('Request failed:', error);
});
}
}
您的 status
函数 returns(承诺)状态 text 用于 400s 或 404s 的响应。您使用 fetch
结果的承诺链无法处理这种可能性;它假定它获得了响应对象。
您可能希望在 400 或 404 上拒绝而不是解决,但如果不是,您需要在 then
处理程序中分支以期望读取 JSON。
您使用漏洞的代码也在覆盖相同的 span
并重复附加它;它最终只会附加一次 last 违规信息。 append
函数并没有提供任何有用的抽象,只是调用 appendChild
.
如果 API 真的 returns 404 for "no breaches" (blech),那么我会去掉 createNode
和 append
,改变status
到此:
function status(response) {
if (response.ok) {
return response.json();
} else if (response.status === 404) { // If the API *really* returns
return []; // a 404 for "no breaches"
} else {
throw new Error(response.statusText);
}
}
然后:
fetch('https://haveibeenpwned.com/api/v2/breachedaccount/' + account.value, {
timeout: 1500,
userAgent: 'test'
})
.then(status)
.then(breaches => {
// No `return` here, the chain isn't passed on and there
// aren't any further resolution handlers
breaches.forEach(check => { // Or a for-of loop
const span = document.createElement("span");
span.innerHTML = `${check.Name}<br/>`;
results.appendChild(span);
});
}).catch(error => {
console.log('Request failed:', error);
});
另外:您的 status
函数表明您没有意识到 then
(和 catch
)创建新的承诺。如果您的 status
函数仅用作 then
处理程序,则没有理由创建任何承诺。它应该只是一个 return 值(由 then
创建的承诺将使用该值解析)或抛出错误(由 then
创建的承诺将拒绝该错误):
// This is equivalent to your current `status` function (assuming it's always
// used as a `then` callback)
function status(response) {
if (response.ok) { // if (response.status >= 200 && response.status < 300) {
// all okay
return response;
} else if (response.status == 404) {
// no breaches
return response.statusText;
} else if (response.status == 400) {
// bad request
return response.statusText;
} else {
throw new Error(response.statusText);
}
}
(我删除了每个分支中 return
之后 的 console.log
行,因为它们无法访问。)