如何使用 fetch ,加请求头, ajax 和 fetch 和

2018-07-06  本文已影响0人  WEB_Jorie

----欢迎查看我的博客----

什么是fetch

  我们之前,过度过来都在用ajax,那么什么是 Fetch ,Fetch 是新的游览器对象, 等同于 XMLHttpRequest对象 。它提供了许多与 XMLHttpRequest 相同的功能,但被设计成更具可扩展性和高效性。

image

ajax

  废话不多说我们来看一下传统的ajax。

var xhr;
if (window.XMLHttpRequest) {
   xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
   try {
     xhr = new ActiveXObject('Msxml2.XMLHTTP');
   } catch (e) {
     try {
       xhr = new ActiveXObject('Microsoft.XMLHTTP');
     } catch (e) {}
   }
}
if (xhr) {
   xhr.onreadystatechange = () =>{
       if (xhr.readyState === 4) {
          if (xhr.status === 200) {
             console.log(xhr.responseText); //返回值传callback
          } else {
                //failcallback
             console.log('There was a problem with the request.');
          }
       } else {
          console.log('still not ready...');
       }
    };
   xhr.open('POST', 'https://www.baidu.com', true);
   // 设置 Content-Type 为 application/x-www-form-urlencoded
   // 以表单的形式传递数据
   xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
   xhr.send('username=admin&password=root');
}

  好我们来做层封装,让他变成我们 jQuery 的 ajax post
如这种形式:

$.ajax({
    method: 'POST', //请求方式
    url: '/api', //url
    data: { username: 'admin', password: 'root' }, //值
    success:function(data){ //成功回掉
        console.log(data)
    },
    error:function(err){
        console.log(err)
    }
})

好的封装开始:

const $ = {};
$.ajax = (obj)=>{
    var xhr;
    if (window.XMLHttpRequest) {
       xhr = new XMLHttpRequest();
    } else if (window.ActiveXObject) { // IE
       try {
         xhr = new ActiveXObject('Msxml2.XMLHTTP');
       } catch (e) {
         try {
           xhr = new ActiveXObject('Microsoft.XMLHTTP');
         } catch (e) {}
       }
    }
    if (xhr) {
       xhr.onreadystatechange = () =>{
           if (xhr.readyState === 4) {
              if (xhr.status === 200) {
                 obj.success(xhr.responseText); //返回值传callback
              } else {
                    //failcallback
                 obj.error('There was a problem with the request.');
              }
           } else {
              console.log('still not ready...');
           }
        };
       xhr.open(obj.method, obj.url, true);
       // 设置 Content-Type 为 application/x-www-form-urlencoded
       // 以表单的形式传递数据
       xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
       xhr.send(util(obj.data));//处理body数据
    }
    
    //处理数据
    const util = (obj)=>{
        var str = ''
        for (key in obj){
            str += key +'='+obj[key]+'&'

        }
        return str.substring(0,str.length-1)
    }
    
}

  ok,咱们已经封装完毕,可以使用了,可是你会发现,这种书写方式很混乱,body,hearder乱七八糟,还有回掉地狱的问题。好的fetch出来了。

fetch的出现

  我们说了,一种东西的诞生有它的道理,他首先解决了回掉地狱的问题因为返回一个 promise 对象 ,对 promise 对象不是很熟悉的同学可以看这篇文章: 你就需要这篇文章,带你搞懂实战的 Promise 对象。同样既然是 promise 对象我们就可以使用 es7 的 async / await 戳这里。好了废话不多说我们看看最基础的 fetch 怎么写吧 。

fetch(url, options).then(function(response) {
  // handle HTTP response
}, function(error) {
  // handle network error
})

  就是这么方便,就是这么简单。 fetch 会先发起一个 option 的请求,确定是否连接成功,然后再发送正式的请求 ,就好比 xhr.readyState === 4 这个一个道理。那有同学就问了,我的逻辑比较复杂 。我的 fetch 要加请求头,参数我要传参传 formData 不是 json。
我们来看fetch发送formdata:

fetch(url,{
    method:"post",
    headers:{
        "Content-type":"application:/x-www-form-urlencoded:charset=UTF-8"
    },
    body:"name=admin&password=123456"
}).then(function(response){
    if(response.ok){
        response.json().then(json => {
              console.log(json.result)
        })
    }
}).catch(function(err){
    console.log("Fetch错误:"+err);
});

  发送json格式也非常简单。

fetch(url,{
    method:"post",
    headers:{
       'Content-Type':'application/json; charset=UTF-8'
    },
    body:JSON.stringify({name:'admin',password:123456})
}).then(function(response){
    if(response.ok){
        response.json().then(json => {
              console.log(json.result)
        })
    }
}).catch(function(err){
    console.log("Fetch错误:"+err);
});

中止 取消 fetch

浏览器已经开始为 AbortControllerAbortSignal 接口(也就是Abort API)添加实验性支持,允许像 Fetch 和 XHR 这样的操作在还未完成时被中止 。请参阅接口页面了解更多详情。但是目前对游览器的支持并不很好,所以我们其实可以换一种思路, 取消 fetch 我们可以从另外一个面入手 ---- 可以取消 promise 。原生的当然不行了,所以我们这里用到了 bluebird

例如多个 fetch:


//传统 promise
var promises = [];
for (var i = 0; i < fileNames.length; ++i) {
    promises.push(fs.readFileAsync(fileNames[i]));
}
Promise.all(promises).then(function() {
    console.log("done");
});

// Using Promise.map:
import Promise from 'bluebird'
Promise.map(fileNames, function(fileName) {
    // Promise.map awaits for returned promises as well.
    return fs.readFileAsync(fileName);
}).then(function() {
    console.log("done");
});

终止取消多个 fetch:

import Promise from 'bluebird'
Promise.map(fileNames, function(fileName) {
    // Promise.map awaits for returned promises as well.
    return fs.readFileAsync(fileName).then(()=>{
                //如果flag = true 就中断。
                if (flag){
                  throw new Error('中断')
                }
            });;
}).then(function() {
    console.log("done");
}).catch(function (err) {
    console.log('Error', err.message)
});

如果取消单个 promise 可以用 .cancel 方法,具体看 bluebird 文档。

Axios 的出现

  从文档中我们可以看出为什么这个会火 ,axios 他的功能非常强大,包括 取消请求 ,进度处理等等。但是我们看的是本质还是 ajax ,在基础上进行了封装和功能的添加

XMLHttpRequests
支持 Promise

//一个post请求

axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

结语

  其实我们看出来, ajax 和 Axios 在客户端都是调用 XMLHttpRequests 对象 ,而我们的 fetch 是一个新的游览器对象 。只不过 ajax 和 Axios 区别就是在 封装了简便的方法,并且提供了一个 promise 对象。

上一篇下一篇

猜你喜欢

热点阅读