学习fetch,从这里开始!

一、fetch() 是什么?

fetch() 是 浏览器内置的 全局 JavaScript 方法,用于发出 http 请求,无需下载安装,可以直接使用。

// 一个简单 http 请求
fetch('http://example.com/movies.json')
    .then(function (response) {
        return response.json();
    })
    .then(function (myJson) {
        console.log(myJson);
    });

二、怎么使用?
1、简单使用实例

fetch() 的第二个参数是 init 对象,用于设置 http 的配置信息。

postData('http://example.com/answer', { answer: 42 })
    .then(data => console.log(data))
    .catch(error => console.error(error))

function postData(url, data) {
    return fetch(url, {
        body: JSON.stringify(data),
        cache: 'no-cache',
        credentials: 'same-origin',
        headers: {
            'user-agent': 'Mozilla/4.0 MDN Example',
            'content-type': 'application/json'
        },
        method: 'POST',
        mode: 'cors',
        redirect: 'follow',
        referrer: 'no-referrer',
    })
        .then(response => response.json())
}
2、配置详细说明
  • method :请求使用的方法,如 GET、POST、PUT、DELETE 等。
  • headers :请求的头信息。
  • body :请求的 body 信息,注意 GET 或 HEAD 方法的请求不能包含 body 信息。
  • mode :请求模式,可用值: cors、no-cors、same-origin
  • credentials :是否发送 cookie 给服务器:omit(任何情况都不发)、same-origin(同源才发)、include(任何情况都发)
  • cache :可用 cache 模式 :default、no-store、reload、no-cache、force-cache、only-if-cached 。
  • redirect :重定向,Chrome中默认使用 follow ;

    • follow (自动重定向)
    • error (发生重定向将自动终止并且抛出错误)
    • manual (手动处理重定向)
  • referrer :发送请求的页面URL,浏览器默认添加到请求Header 中。设置成 no-referrer 表示不添加。
  • referrerPolicy :什么时候使用 referrer,可用值: no-referrer、 no-referrer-when-downgrade、origin、origin-when-cross-origin、unsafe-url 。
  • integrity :设定资源对应 hash 值,保证资源的完整性。

三、使用场景
1、发送带凭证请求
// 同不同源都会发送 带凭证的请求
fetch('https://example.com', {
  credentials: 'include'
})

// 只有同源才发送 带凭证请求
fetch('https://example.com', {
  credentials: 'same-origin'
})

// 同不同源都发送 不带凭证的请求
fetch('https://example.com', {
  credentials: 'omit'
})

2、上传 JSON 数据
var url = 'https://example.com/profile';
var data = {username: 'example'};

fetch(url, {
  method: 'POST', // or 'PUT'
  body: JSON.stringify(data), // data can be `string` or {object}!
  headers: new Headers({
    'Content-Type': 'application/json'
  })
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));

3、上传文件

可以通过 HTML 元素,FormData对象 和 fetch() 方法 上传文件。

var formData = new FormData();
var fileField = document.querySelector("input[type='file']");

formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);

fetch('https://example.com/profile/avatar', {
  method: 'PUT',
  body: formData
})
.then(response => response.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));

4、上传多个文件

可以通过HTML 元素,FormData() 和 fetch() 上传文件。

var formData = new FormData();
var photos = document.querySelector("input[type='file'][multiple]");

formData.append('title', 'My Vegas Vacation');
// formData 只接受文件、Blob 或字符串,不能直接传递数组,所以必须循环嵌入
for (let i = 0; i < photos.files.length; i++) {
    formData.append('photo', photos.files[i]);
}

fetch('https://example.com/posts', {
  method: 'POST',
  body: formData
})
.then(response => response.json())
.then(response => console.log('Success:', JSON.stringify(response)))
.catch(error => console.error('Error:', error));

5、检测请求是否成功

可用下面方法捕获 网络故障、服务器端CORS限制 的错误,做进一步的处理(譬如,写日志等)。

fetch('flowers.jpg').then(function (response) {
    if (response.ok) {
        return response.blob();
    }
    throw new Error('Network response was not ok.');
}).then(function (myBlob) {
    var objectURL = URL.createObjectURL(myBlob);
    myImage.src = objectURL;
}).catch(function (error) {
    console.log('There has been a problem with your fetch operation: ', error.message);
});

6、新建Request,发送 http 请求
var myHeaders = new Headers();

var myInit = {
    method: 'GET',
    headers: myHeaders,
    mode: 'cors',
    cache: 'default'
};

var myRequest = new Request('flowers.jpg', myInit);

fetch(myRequest).then(function (response) {
    return response.blob();
}).then(function (myBlob) {
    var objectURL = URL.createObjectURL(myBlob);
    myImage.src = objectURL;
});

四、Headers
1、创建 Headers 对象
// 法一
var content = "Hello World";
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
myHeaders.append("Content-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");

// 法二
myHeaders = new Headers({
    "Content-Type": "text/plain",
    "Content-Length": content.length.toString(),
    "X-Custom-Header": "ProcessThisImmediately",
});

2、Headers对象的方法

Headers 对象提供的读取、设置、判断等方法。

console.log(myHeaders.has("Content-Type")); // true
console.log(myHeaders.has("Set-Cookie")); // false
myHeaders.set("Content-Type", "text/html");
myHeaders.append("X-Custom-Header", "AnotherValue");

console.log(myHeaders.get("Content-Length")); // 11
console.log(myHeaders.getAll("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]

myHeaders.delete("X-Custom-Header");
console.log(myHeaders.getAll("X-Custom-Header")); // [ ]

3、属性报错

设置 Headers 中不支持的属性会报错。

var myResponse = Response.error();
try {
    myResponse.headers.set("Origin", "http://mybank.com");
} catch (e) {
    console.log("Cannot pretend to be a bank!");
}

4、数据格式确认

获取到数据后,先做数据格式检查,符合预想格式后再做进一步处理。

fetch(myRequest).then(function (response) {
    if (response.headers.get("content-type") === "application/json") {
        return response.json().then(function (json) {
            // 做进一步数据处理
        });
    } else {
        console.log("Oops, we haven't got JSON!");
    }
});

5、guard 属性

Headers 对象可用在 请求发送 和 响应接受 中,其有个 guard 属性,用于表示那些参数是只读。

  • none:默认的
  • request:从 request 中获得的 headers(Request.headers)只读
  • request-no-cors:从不同域(Request.mode no-cors)的 request 中获得的 headers 只读
  • response:从 response 中获得的 headers(Response.headers)只读
  • immutable:在 ServiceWorkers 中最常用的,所有的 headers 都只读。

6、Content-Type

request和response(包括 fetch() 方法)都会试着自动设置 Content-Type。如果没有设置 Content-Type 值,发送的请求也会自动设值。


五、Response 对象

fetch 发出请求后,返回的是 Response 对象,其常用属性有:

  • Response.status :整数(默认值为200)为response的状态码。
  • Response.statusText :字符串(默认值为"OK"),该值与 HTTP 状态码消息对应。
  • Response.ok :该属性是来检查response的状态是否在 200 - 299(包括200 和 299)这个范围内。该属性返回一个布尔值。

六、body 对象

请求和响应 中都可以有 body 对象,Request 和 Response 对象 都实现了以下方法,用于获取 body 不同格式的内容:arrayBuffer()、blob()、json()、text()、formData()


七、检查 fetch 是否可用?
if(self.fetch) {
    // run my fetch request here
} else {
    // do something with XMLHttpRequest?
}

八、其他
1、fetch 与 jQuery.ajax() 的不同点
  • fetch() 收到代表错误的 HTTP 状态码(譬如404 或500),会设置 Promise 的 resolve 值为false,但不会reject,只有 网络故障 或 请求被阻止 才会 reject。
  • fetch() 可以接受跨域 cookies 和 建立跨域会话。
  • fetch() 只有使用了credentials 选项,才会发送 cookies,但要符合同源( same-origin)规则。

2、fetch 与 axios 的区别

详情,看这里!


3、CORS(跨域访问)错误
/* Error:
  Access to fetch at '×××'
  from origin '×××' has been blocked by CORS policy: No
  'Access-Control-Allow-Origin' header is present on the requested
  resource. If an opaque response serves your needs, set the request's
  mode to 'no-cors' to fetch the resource with CORS disabled.
*/

相关跨域访问的问题,看这里!


九、参考文档

你可能感兴趣的