Javascript - 如何知道 Fetch API 中响应的类型?
Javascript - How to know the type of the response in Fetch API?
如何知道 Fetch 中响应的类型 API?
在 XMLHttpRequest 中,有 responseType
property which indicates the type of the returned response's body (json, text, blob, etc.). While in the Fetch API response,即使有有用的方法来解析它的主体(json()
、text()
、blob()
等),我仍然没有找到任何 属性 像 XMLHttpRequest 的 responseType
属性 来指示响应的类型。
我认为您可以检查 content-type 响应的 headers,如下所示:
response.headers.get("content-type")
我认为 orangespark 是对的。 content-type
响应 header 应该 被使用。
如果 content-type
header 缺失或无效。 top 进一步处理响应即可:
When extract a MIME type returns failure or a MIME type whose essence is incorrect for a given format, treat this as a fatal error. Existing web platform features have not always followed this pattern, which has been a major source of security vulnerabilities in those features over the years. In contrast, a MIME type’s parameters can typically be safely ignored.
https://fetch.spec.whatwg.org/#content-type-header
由于有许多有效的媒体类型,一些库 lazy probe Content-Type
header: response.headers.get("content-type").includes('json')
for json
存在,在 response.json()
被调用之前。
There are 1500+ Media types registered with the IANA which can be set as the Content-Type for a request.
如果content-type
没有设置(或忘记设置)。 text/plain
的 default 可能由服务器设置,这将 'break' 您的响应处理。
如果 content-type
不是可接受的媒体类型之一,或者 body
不匹配 content-type
...
要求:
accept: text/html, image/avif;q=0.9, image/apng;q=0.8
响应(差):
content-type: application/json
...您可以在阅读 body
之前让您的应用程序更加故障安全并 clone()
response
。所以你仍然可以 return JSON 例如无法解析为 JSON.
的 text
响应错误
const response2 = response.clone();
let data;
try {
data = await response.json(); // SyntaxError: Unexpected token in JSON
} catch (e) {
text = await response2.text(); // response clone can still read as a fallback
data = {
error: e.message,
invalidJson: text
};
}
您可以使用 response.blob()
作为 response.text()
、response.json()
、...
的替代方案
returned Blob
有一个 属性 blob.type
保存 content-type
header 值。
这里有一些示例,如何处理这些斑点:
- Blob SVG:
image/svg+xml
内容
- Blob HTML:
text/html
内容
- Blob JSON
application/json
内容
- Blob JSON
application/octet-stream
内容
- Blob 错误
???/???
内容
(async() => {
const c = document.body;
imageBlob = () => {
const svg = `<svg viewBox="0 0 200 200" width="80" height="80" xmlns="http://www.w3.org/2000/svg"><path fill="#FF0066" d="M31.5,-16.8C35.9,3.2,31,19.6,16.3,32.8C1.5,46,-23.2,55.9,-36.6,46.9C-50.1,38,-52.3,10.1,-44.3,-14.8C-36.4,-39.8,-18.2,-61.9,-2.3,-61.2C13.6,-60.4,27.2,-36.8,31.5,-16.8Z" transform="translate(100 100)" /></svg>`;
return new Blob(
[svg], {
type: 'image/svg+xml'
}
);
}
htmlBlob = () => {
return new Blob(
['<span>HTML <b style="color: red">blob</b></span>'], {
type: 'text/html'
}
);
}
jsonBlob = type => {
const json = {
a: 1,
b: {
c: 'val'
}
}
const jsonStr = JSON.stringify(json);
return new Blob([jsonStr], {
type
});
}
// Blob instances you might get from: await response.blob()
// blob.type is set from 'Content-Type' header of its response
const blobs = [
imageBlob(), // 1
htmlBlob(), // 2
jsonBlob('application/json'), // 3
jsonBlob('application/octet-stream'), // 4
jsonBlob('???/???') // 5
]
for (const [i, b] of Object.entries(blobs)) {
c.append(Object.assign(document.createElement('h3'), {
textContent: `${1+parseInt(i)}. ${b.type}:`
})) // b.type === 'Content-Type'━━┛
if (b.type.startsWith('text/html')) { // 1
const text = await b.text();
c.append(Object.assign(document.createElement('div'), {
innerHTML: text
}));
} else if (b.type.startsWith('image/')) { // 2
c.append(Object.assign(document.createElement('img'), {
src: URL.createObjectURL(b)
}));
} else if (b.type.startsWith('application/json')) { // 3
c.append(Object.assign(document.createElement('pre'), {
textContent: JSON.stringify(JSON.parse(await b.text()), null, ' ')
}));
} else if (b.type.startsWith('application/octet-stream')) { // 4
c.append(Object.assign(document.createElement('a'), {
textContent: 'download json',
href: URL.createObjectURL(b),
download: 'data.json'
}));
} else { // 5
// .... create a clone Response from blob
// -> response2 = new Response(await response1.blob())
const response2 = new Response(b);
const b2 = await response2.blob(); // .json() .text(),...
const text2 = await b2.text();
console.log('blob2', text2, b2.type);
// Blogs are b === b2
const text = await b.text();
console.log('blob1', text, b.type);
console.log('blob2 === blob1', text === text2); // true
}
}
c.append(Object.assign(document.createElement('h3'), {
innerHTML: ` <br> `
}))
})()
如何知道 Fetch 中响应的类型 API?
在 XMLHttpRequest 中,有 responseType
property which indicates the type of the returned response's body (json, text, blob, etc.). While in the Fetch API response,即使有有用的方法来解析它的主体(json()
、text()
、blob()
等),我仍然没有找到任何 属性 像 XMLHttpRequest 的 responseType
属性 来指示响应的类型。
我认为您可以检查 content-type 响应的 headers,如下所示:
response.headers.get("content-type")
我认为 orangespark 是对的。 content-type
响应 header 应该 被使用。
如果
content-type
header 缺失或无效。 top 进一步处理响应即可:When extract a MIME type returns failure or a MIME type whose essence is incorrect for a given format, treat this as a fatal error. Existing web platform features have not always followed this pattern, which has been a major source of security vulnerabilities in those features over the years. In contrast, a MIME type’s parameters can typically be safely ignored. https://fetch.spec.whatwg.org/#content-type-header
由于有许多有效的媒体类型,一些库 lazy probe
Content-Type
header:response.headers.get("content-type").includes('json')
forjson
存在,在response.json()
被调用之前。There are 1500+ Media types registered with the IANA which can be set as the Content-Type for a request.
如果
content-type
没有设置(或忘记设置)。text/plain
的 default 可能由服务器设置,这将 'break' 您的响应处理。如果
content-type
不是可接受的媒体类型之一,或者body
不匹配content-type
...要求:
accept: text/html, image/avif;q=0.9, image/apng;q=0.8
响应(差):
content-type: application/json
...您可以在阅读
的body
之前让您的应用程序更加故障安全并clone()
response
。所以你仍然可以 return JSON 例如无法解析为 JSON.text
响应错误const response2 = response.clone(); let data; try { data = await response.json(); // SyntaxError: Unexpected token in JSON } catch (e) { text = await response2.text(); // response clone can still read as a fallback data = { error: e.message, invalidJson: text }; }
您可以使用
的替代方案response.blob()
作为response.text()
、response.json()
、...returned
Blob
有一个 属性blob.type
保存content-type
header 值。这里有一些示例,如何处理这些斑点:
- Blob SVG:
image/svg+xml
内容 - Blob HTML:
text/html
内容 - Blob JSON
application/json
内容 - Blob JSON
application/octet-stream
内容 - Blob 错误
???/???
内容
- Blob SVG:
(async() => {
const c = document.body;
imageBlob = () => {
const svg = `<svg viewBox="0 0 200 200" width="80" height="80" xmlns="http://www.w3.org/2000/svg"><path fill="#FF0066" d="M31.5,-16.8C35.9,3.2,31,19.6,16.3,32.8C1.5,46,-23.2,55.9,-36.6,46.9C-50.1,38,-52.3,10.1,-44.3,-14.8C-36.4,-39.8,-18.2,-61.9,-2.3,-61.2C13.6,-60.4,27.2,-36.8,31.5,-16.8Z" transform="translate(100 100)" /></svg>`;
return new Blob(
[svg], {
type: 'image/svg+xml'
}
);
}
htmlBlob = () => {
return new Blob(
['<span>HTML <b style="color: red">blob</b></span>'], {
type: 'text/html'
}
);
}
jsonBlob = type => {
const json = {
a: 1,
b: {
c: 'val'
}
}
const jsonStr = JSON.stringify(json);
return new Blob([jsonStr], {
type
});
}
// Blob instances you might get from: await response.blob()
// blob.type is set from 'Content-Type' header of its response
const blobs = [
imageBlob(), // 1
htmlBlob(), // 2
jsonBlob('application/json'), // 3
jsonBlob('application/octet-stream'), // 4
jsonBlob('???/???') // 5
]
for (const [i, b] of Object.entries(blobs)) {
c.append(Object.assign(document.createElement('h3'), {
textContent: `${1+parseInt(i)}. ${b.type}:`
})) // b.type === 'Content-Type'━━┛
if (b.type.startsWith('text/html')) { // 1
const text = await b.text();
c.append(Object.assign(document.createElement('div'), {
innerHTML: text
}));
} else if (b.type.startsWith('image/')) { // 2
c.append(Object.assign(document.createElement('img'), {
src: URL.createObjectURL(b)
}));
} else if (b.type.startsWith('application/json')) { // 3
c.append(Object.assign(document.createElement('pre'), {
textContent: JSON.stringify(JSON.parse(await b.text()), null, ' ')
}));
} else if (b.type.startsWith('application/octet-stream')) { // 4
c.append(Object.assign(document.createElement('a'), {
textContent: 'download json',
href: URL.createObjectURL(b),
download: 'data.json'
}));
} else { // 5
// .... create a clone Response from blob
// -> response2 = new Response(await response1.blob())
const response2 = new Response(b);
const b2 = await response2.blob(); // .json() .text(),...
const text2 = await b2.text();
console.log('blob2', text2, b2.type);
// Blogs are b === b2
const text = await b.text();
console.log('blob1', text, b.type);
console.log('blob2 === blob1', text === text2); // true
}
}
c.append(Object.assign(document.createElement('h3'), {
innerHTML: ` <br> `
}))
})()