js网络请求的点点滴滴(axios、fetch、ajax)

不问归期 提交于 2020-03-15 01:45:37

 

一、什么是网络请求,网路请求的类型 

  • 1.1 什么是网路请求,网路请求关心哪些内容

    传入基本参数(url,请求方式) 请求参数、请求参数类型 设置请求头 获取响应的方式 获取响应头、响应状态、响应结果 异常处理 携带cookie设置 跨域请求

  • 1.2网路请求的类型

    同步请求 异步请求

二、同步请求的模式

三、异步请求的模式

   

四、当前流行的异步请求方案

axios、fetch、ajax

问题一:axios、fetch与ajax有什么区别?

主要区别是 axios、fetch请求后都支持Promise对象API,ajax只能用回调函数。

  • Ajax

Ajax被认为是(Asynchronous JavaScript and XML)的缩写。现在,允许浏览器与服务器通信而无须刷新当前页面的技术都被叫做Ajax。依赖的传输对象:XMLHttpRequestajax无需多言,如果想要更多了解,参考以下链接:ajax详解

  • axios:

代码示例

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

Vue2.0之后推荐大家用axios替换JQuery ajax,

  • Axios本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范,它有以下几条特性:
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 客户端支持防止CSRF
  • 提供了一些并发请求的接口(重要,方便了很多的操作)

Axios既提供了并发的封装,也没有fetch的各种问题,而且体积也较小,推荐大家使用。axios-详解  axios-npm官网

1、Axios 是一个基于 promise 的 HTTP 库,支持promise所有的API
2、它可以拦截请求和响应
3、它可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据
4、安全性更高,客户端支持防御 XSRF

  • axios请求方式
axios.request(config);

axios.get(url[,config]);

axios.delete(url[,config]);

axios.head(url[,config]);

axios.post(url[,data[,config]]);

axios.put(url[,data[,config]])

axios.patch(url[,data[,config]])

并发请求(concurrency),即是帮助处理并发请求的辅助函数

//iterable是一个可以迭代的参数如数组等
axios.all(iterable)
//callback要等到所有请求都完成才会执行
axios.spread(callback)
  • fetch

示例

fetch(url).then(res => {
	console.log(res)
}).catch(err => {
	console.log(err)
})

Fetch API 提供了一个 JavaScript接口,用于访问和操纵HTTP管道的部分,例如请求和响应。它还提供了一个全局 fetch()方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。

Fetch 优点主要有:

  • 语法简洁,更加语义化

  • 基于标准 Promise 实现,支持 async/await

  • 同构方便,使用 isomorphic-fetch

不过原生支持率并不高,引入下面这些 polyfill 后可以完美支持 IE8+ :

  • 由于 IE8 是 ES3,需要引入 ES5 的 polyfill: es5-shim, es5-sham

  • 引入 Promise 的 polyfill: es6-promise

  • 引入 fetch 探测库:fetch-detector

  • 引入 fetch 的 polyfill: fetch-ie8

  • 可选:如果你还使用了 jsonp,引入 fetch-jsonp

  • 可选:开启 Babel 的 runtime 模式,现在就使用 async/await

问题二:Promise对象是什么?关于Promise对象的详细解析

Promise对象是ES6( ECMAScript 2015 )对于异步编程提供的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。

传统回调:

// 当参数a大于10且参数func2是一个方法时 执行func2
function func1(a, func2) {
   if (a > 10 && typeof func2 == 'function') {
       func2()
   }
}

func2(11, function() {
   console.log('this is a callback')
})

Promise对象改写:

function func1(a){
	return new Promise((resolve,reject) => {
    	if(a > 10){
        	resolve(a)
        }else{
        	reject(b)
        }
    })
};

func1('11').then(res => {
	console.log('success');
}).catch(err => {
	console.log('error');
})

Promise对象的两个特点:

1、对象的状态不受外界影响。

Promise对象有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。

Promise对象的状态改变,只有两种可能:

从pending变为fulfilled和从pending变为rejected。

只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。

如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

Promise对象实例的两个参数,resolve 和 reject:

Promise构造函数接受一个函数作为参数,该函数的两个参数分别resolve  reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。

resolve函数的作用是: 将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 fulfilled),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;

reject函数的作用是: 将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise对象实例的方法,then 和 catch:

.then方法: 用于指定调用成功时的回调函数。

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例),因此可以采用链式写法,即then方法后面再调用另一个then方法。

.catch方法: 用于指定发生错误时的回调函数。

五、跨域的问题

问题一:什么是JS的同源策略和跨域问题?

同源策略:
所谓同源策略,指的是浏览器对不同源的脚本或者文本的访问方式进行的限制。比如源a的js不能读取或设置引入的源b的元素属性。
同源指两个页面具有相同的协议,主机(也常说域名),端口,三个要素缺一不可。

URL1 URL2 说明 是否允许通信
http://www.foo.com/js/a.js http://www.foo.com/js/b.js 协议、域名、端口都相同 允许
http://www.foo.com/js/a.js http://www.foo.com:8888/js/b.js 协议、域名相同,端口不同 不允许
https://www.foo.com/js/a.js http://www.foo.com/js/b.js 主机、域名相同,协议不同 不允许
http://www.foo.com/js/a.js http://www.bar.com/js/b.js 协议、端口相同,域名不同 不允许
http://www.foo.com/js/a.js http://foo.com/js/b.js 协议、端口相同,主域名相同,子域名不同 不允许

同源策略限制的不同源之间的交互主要针对的是 js中的XMLHttpRequest等请求,下面这些情况是完全不受同源策略限制的。

1、页面中的链接,重定向以及表单提交是不会受到同源策略限制的。

2、跨域资源嵌入是允许的,当然,浏览器限制了Javascript不能读写加载的内容。

即我们需要向不同源的 后台接口 发送 http请求去请求数据。

vue-cli开发环境开发的时候一定会涉及到跨域问题

因为vue-cli开发环境启动本地一个 localhost:端口号 node服务器,此时去请求数据接口一定是跨域的。

问题二:如何解决跨域问题?

1、通过 jquery 的 jsonp 形式解决跨域问题(小学生回答模式)

$.ajax({
    url:'...../data.js',//可以不是本地域名 
    type:'get',
    dataType:'jsonp',  //jsonp格式访问
    jsonpCallback:'aa'  //获取数据的函数
})

2、在vue-cli项目中的 config 文件夹下的 index.js 配置文件中,配置 dev对象的 proxyTable对象,可通过node.js的代理服务器来实现跨域请求。

module.exports = {
    publicPath: '/',
    outputDir: 'dist',
    assetsDir: 'static',
    configureWebpack: {
        devtool:'eval-source-map'
    },
    devServer: {
        port: 8080,
        open: true,
        overlay: {
            warnings: false,
            errors: true
        },
        proxy: {
            '/api': {
                target: 'http://api/',
                secure: false,
                changeOrigin: true,
                pathRewrite: {
                    '/api': '/api'
                }
            }
        }
    },
};

3、在服务器响应客户端的时候,带上 Access-Control-Allow-Origin:* 头信息 [推荐使用]

public class testFilter implements Filter { 
public void doFilter(ServletRequest request, ServletResponse resp, FilterChain chain) 
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp; 
response.setHeader("Access-Control-Allow-Origin", "*"); //解决跨域访问报错 
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE"); 
response.setHeader("Access-Control-Max-Age", "3600"); //设置过期时间 
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization"); 
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 支持HTTP 1.1. 
response.setHeader("Pragma", "no-cache"); // 支持HTTP 1.0. response.setHeader("Expires", "0"); 
chain.doFilter(req, res); 
}

4、通过负载均衡服务工具(nginx)进行url转发 

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    location / {
        proxy_pass  http://web1;
        proxy_set_header        Host            $host;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        index  index.html index.jsp login.jsp index.htm;

        #root   html;
        #index  index.html index.htm;
    }

    location /admin {
        proxy_pass  http://web2;
        proxy_set_header        Host            $host;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        index  index.html index.jsp login.jsp index.htm;
    }
    ...
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!