FetchAPI 的使用

Fetch是什么?

  fetch是用来取代传统的XMLHttpRequest的。 它的优点很多,包括链式调用的语法、返回promise等。

  fetch api是基于promise的设计,它是为了取代传统xhr的不合理的写法而生的。

  传统的XMLHttpRequest请求闲的非常的杂乱,而优雅的ajax又不得不额外加载jQuery这个80K左右的框架

  但是现在,我们可以使用Fetch,提供了对 Request 和 Response (以及其他与网络请求有关的)对象的通用定义,

  它还提供了一种定 义,将 CORS 和 HTTP

  原生的头信息结合起来,取代了原来那种分离的定义。

  But,Fetch 兼容性,可以看到,兼容性很差,移动端全军覆没,不过可以使用Fetch polyfill

  链接:https://www.jianshu.com/p/11f64a03d3f3
 
  传统的xhr请求写起来非常的混乱,如:
 1 var xhr = new XMLHttpRequest();
 2 xhr.open('GET', url);
 3 xhr.responseType = 'json';
 4 
 5 xhr.onload = function() {
 6   console.log(xhr.response);
 7 };
 8 
 9 xhr.onerror = function() {
10   console.log("Oops, error");
11 };
12 
13 xhr.send();

  但是使用fetch之后,如:

1 fetch(url).then(function(response) {
2   return response.json();
3 }).then(function(data) {
4   console.log(data);
5 }).catch(function(e) {
6   console.log("Oops, error");
7 });

  所以是这种链式调用的风格看上去会非常舒服。

  如果我们再使用了箭头函数就会更加简洁了。 

1 fetch(url).then(response => response.json())
2   .then(data => console.log(data))
3   .catch(e => console.log("Oops, error", e))

基本使用方法

fetch必须接受一个资源路径作为参数,并且返回了一个promise,所以我们可以直接使用链式调用的方式。 

 1 fetch("/getAllProduct").then(function(res) {
 2             return res.json();
 3         }).then(function (data) {
 4             if (data.code == 200) {
 5               console.log('获取到所有产品' ,data.data);
 6               that.props.addAllProduct(data.data);
 7             } else {
 8               console.log(data.message);
 9             }
10         })

这样,我们就可以发送一个ajax请求。

  1 /* 对客户端的返回数据封装
  2  * @param [code] (number) code为返回的状态码
  3  * @param [message] (string) message为返回的信息
  4  * @param [data] (any) data是可选的,为返回给前端的数据
  5  */
  6 // 注意: retrunJson中的res为node处理接口的回调函数中的res,这个是必须的。
  7 function returnJson(res, code, message, data) {
  8     var response = {
  9         code: code,
 10         message: message
 11     };
 12     if (typeof data !== 'undefined') {
 13         response.data = data;
 14     }
 15     res.json(response);
 16    // 返回这个请求之后,必须要 res.end()表示请求的结束,否则后台可能会崩溃。
 17     res.end();
 18 }
 19 
 20 router.post('/register', function (req, res) {
 21     let userName = req.body.username,
 22         password = req.body.password,
 23         passwordAgain = req.body.passwordAgain,
 24         type = req.body.type;
 25     console.log(userName, password, type);
 26     if (type == 1) {
 27         if (password == passwordAgain) {
 28             let managerId = uuidv1();
 29 
 30             console.log(userName, password, passwordAgain);
 31 
 32             var newUser = new Manager({
 33                 name: userName,
 34                 password: password,
 35                 type: req.body.type,
 36                 managerId: managerId
 37             });
 38 
 39             Manager.find(userName, function (err, user) {
 40                 if (err) {
 41                     returnJson(res, 5001, '服务器错误,注册失败');
 42                 } else {
 43                     if (user !== null) {
 44                         returnJson(res, 4003, "此用户已经注册!");
 45                     } else {
 46                         // 如果符合条件,就注册该用户,将数据保存在数据库。
 47                         newUser.save(function (err, user) {
 48                             if (err) {
 49                                 // 服务器端错误,失败返回状态码500
 50                                 returnJson(res, 500, "用户注册失败!");
 51                             } else {
 52                                 // user数据较简单,直接传递user即可,如果复杂,我们可以考虑使用对象形式传递更多数据。
 53                                 returnJson(res, 200, "用户注册成功!", user);
 54                             }
 55                         });
 56                     }
 57                 }
 58             });
 59         } else {
 60             returnJson(res, 4001, "用户两次输入密码不一致!");
 61         }
 62     } else if( type == 2) {
 63 
 64          if (password == passwordAgain) {
 65             let userId = uuidv1();
 66 
 67             console.log(userName, password, passwordAgain);
 68 
 69             var newUser = new User({
 70                 name: userName,
 71                 password: password,
 72                 type: req.body.type,
 73                 userId: userId
 74             });
 75 
 76             User.find(userName, function (err, user) {
 77                 if (err) {
 78                     returnJson(res, 5001, '服务器错误,注册失败');
 79                 } else {
 80                     if (user !== null) {
 81                         returnJson(res, 4003, "此用户已经注册!");
 82                     } else {
 83                         // 如果符合条件,就注册该用户,将数据保存在数据库。
 84                         newUser.save(function (err, user) {
 85                             if (err) {
 86                                 // 服务器端错误,失败返回状态码500
 87                                 returnJson(res, 500, "用户注册失败!");
 88                             } else {
 89                                 // user数据较简单,直接传递user即可,如果复杂,我们可以考虑使用对象形式传递更多数据。
 90                                 returnJson(res, 200, "用户注册成功!", user);
 91                             }
 92                         });
 93                     }
 94                 }
 95             });
 96         } else {
 97             returnJson(res, 4001, "用户两次输入密码不一致!");
 98         }
 99     }
100 });

这样,我们就可以处理一个ajax请求。

注意点:

1、fetch() 返回的是一个Promise对象。

  fetch使用的promise对象可以使得我们使用同步的方式写异步函数。

 

2、 fetch api是可以结合 async 和 await 来使用的。 

  fetch是基于promise实现的,但是使用promise的写法,我们还是可以看到callback的影子,如果结合 async和await来使用,还是非常不错的。

 

3、 Fetch api 提供的spi囊括但是不限于xhr的所有功能。

 

4、 fetch api 可以跨域。 

  参考: https://fetch.spec.whatwg.org/#http-cors-protocol

  跨域请求必须包括  Origin 作为header. 

5、fetch提供了对request和response对象的通用定义。

  Fetch 提供了对 Request 和 Response (以及其他与网络请求有关的)对象的通用定义。所以在一个Fetch请求中,完全可以只使用Request 和 Response两个对象,通过Request 设置参数,通过Response 对返回值进行处理。 

 所以,我们可以将一个fetch定义如下:

 1 var myHeaders = new Headers();
 2 myHeaders.append('Content-Type', 'image/jpeg');
 3 var option = { method: 'GET',
 4     headers: myHeaders,
 5     mode: 'cors',
 6     cache: 'default' };
 7 var myRequest = new Request('https://api.github.com/users/mzabriskie',option);
 8 fetch(myRequest).then(function(response) {
 9     ... 
10 });

参考文章: https://github.com/camsong/blog/issues/2

原文地址:https://www.cnblogs.com/wfhking/p/9464034.html