一、同源策略
什么是同源策略?
同源策略(Same-origin Policy):为了保证浏览器的信息安全,浏览器采用同源策略,保证当前源中的资源只能在当前的源中使用;其他源如果需要使用当前源资源,需要特殊技术,这种A源访问B源的资源的通信称为跨域;
示例:
let xhr = new XMLHttpRequest();xhr.open('GET', 'https://www.baidu.com/', true);xhr.onreadystatechange = function () {if (xhr.readyState === 4 && xhr.status === 200) {console.log('xxx')}};xhr.send();
- 以上请求会报错:
 
Access to XMLHttpRequest at 'https://www.baidu.com/' from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
当出现以上错误时说明你正在进行一个跨域的操作;
同源策略的要求:
同源策略要求通信的两个源的协议、域名、端口号要相同,如果三者中任意一个不同就是不满足同源策略;不满足同源策略的通信就是跨域;
常用的跨域解决方案:
- JSONP
 - 服务端转发,因为同源策略只在客户端存在,在服务端是不存在的;所以可以由服务端转发请求;
 - nginx 转发,nginx 是服务器应用程序,它可以接受客户端的请求,然后根据规则可以配置自动转发;
 - CORS: Cross-Origin-Resource-Sharing: 需要目标域设置 Access-Control-Allow-Origin 头信息;
 
二、JSONP
JSONP 是一种常用的解决跨域的方式;
原理:
利用 script 的 src 属性是不受同源策略约束的,可以访问不同服务器或者端口号下的数据
- 提前声明一个叫做 fn 的函数,给 fn 设置一个形参;
 - 在页面给 script 的 src 的指向的路径拼接一个 callback 属性,callback=fn;当浏览器解析到这个 script 标签时,会向 src 指向的路径发起 http 请求;
 - 服务器收到这个请求后,会返回一个 fn (这里面是服务器返回的数据)
 - fn({xxx}) 这个是让 fn 执行,小括号里面就是服务器发送给我们的数据
 
示例:
JS代码:
function fn(data) {console.log(data);}
HTML代码
<script src="http://matchweb.sports.qq.com/kbs/calendar?columnId=100000&callback=fn"></script>
三、Promise
Promise 是什么?
Promise: 是浏览器新增的内置类,用来管理异步;Promise 本身是同步的,是用来管理异步的;传递给 Promise 的构造函数的回调函数是同步执行的;
let p = new Promise(function (resolve, reject) {// 这个函数中处理异步});
Promise实例对象有三种状态;
- pending: 已经初始化,正在处理异步
 - fulfilled: 异步处理成功
 - rejected: 异步处理失败
 
值得注意的是,Promise 的状态一旦发生变更,就会凝固,不会在发生变化;
Promise 如何处理异步?
let p2 = new Promise(function (resolve, reject) {// 这个函数是同步执行的setTimeout(function () {resolve('abc') // resolve 的实参会传递给 then 方法的第一个回调函数;})});
- 在创建Promise示例时传递的回调函数中,存放的是异步执行的任务;
 - resolve 当异步处理成功后执行的,执行的是一个事件池,收集了后面所有的 then 方法的第一个参数;
 - reject 当异步处理失败后执行的,执行的也是一个事件池,收集了后面所有的 then 方法的第二个参数;
 
p2.then(function (data) {console.log(1);console.log(data);// throw 'new err';// return 'xyz'return new Promise(function (resolve, reject) {resolve('就是想解决')})}, function (err) {console.log(2);console.log(err)}).then(function (data2) {console.log(3);console.log(data2)// then方法}, function (err2) {console.log(4);console.log(err2)});
promise 实例对象的第一个 then 方法的回调函数会根据 new Promise() 时异步处理的情况来决定
如果是 resolve 状态,就会执行第一个 then 方法的第一个回调函数,resolve 时传递的实参会传递给第一函数;
如果是 reject 就会执行第二个,reject 时传递的实参会传给第二个函数
但是后面的 then 方法里面的回调函数执行哪一个取决于执行前面的 then 方法中函数执行的情况;
如果前一个 then 中回调没有返回 promise 实例,无论是第一个还是第二个执行成功了,都会执行后面的 then 的第一个回调函数。但是前一个 then 方法中报错了,就会执行第二个;
- 如果前一个 then 方法中返回的是一个 promise 实例,后面的 then 方法中执行哪个取决于上一个 then 中返回的 promise 实例的状态,如果是 resolve 了,就会执行后面的第一个函数,如果是 reject 了,就会执行第二个函数;
 
四、Promise用法示例
- 首先请求 aside.json,然后从 aside.json 中取得最后一条数据的 id,然后再请求 banner.json。最后把 banner.json 输出
 
使用jq
$.ajax({url: 'aside.json',type: 'get',cache: false,error (err) {},success (res) {let [ , ,third] = res;$.ajax({url: 'banner.json',type: 'get',cache: false,error (err) {},success (data) {console.log(data);}})}});
我们发现,上面代码中一层嵌套一层,如果接口多了,那么这种代码组织起来将会十分不便;
使用Promise
let p = new Promise(function (resolve, reject) {$.ajax({url: 'aside.json',type: 'GET',cache: false,error(err) {reject(err)},success (data) {resolve(data)}})});p.then(([,, third]) => {return new Promise(function (resolve, reject) {$.ajax({url: 'banner.json',type: 'get',cache: false,error(err) {reject(err)},success (data) {resolve(data)}})})}).then((banner) => {console.log(banner)}).catch((err) => {console.log(err)});
- 一般情况下,then 只放一个成功的回调函数,会把失败的回调函数中放在 catch 函数中;
 
五、Promise.all() 方法
- 现在有两个接口,要求必须等着两个接口全部请求完成后才能渲染数据;
 
类似于上面这种场景就会用到 Promise 的 all 方法;
Promise.all([promise实例1, promise实例2])
- Promise.all 是 Promise 的静态方法,接受一个有多个 promise 实例组成的数组,并且返回一个新的 Promise 实例;
 - 如果数组中所有的 Promise 实例的状态都变成 resolve,那么返回的新的 Promise 实例的状态才能变成 resolve;
 - 如果有一个失败,那么新返回的 Promise 实例的状态就会变为失败;
 - 同时,会把数组中的 promise 实例成功的数据组成一个新的数组,传递给后面 then 方法的第一个函数;
 
示例:
function queryFn(url) {return new Promise((resolve, reject) => {$.ajax({url: url,cache: false,error(err) {reject(err)},success (data) {resolve(data)}})})}Promise.all([queryFn('aside.json'), queryFn('banner.json')]).then((dataArr) => {console.log(dataArr)}).catch((err) => {console.log(err)});
【发上等愿,结中等缘,享下等福,择高处立,寻平处住,向宽处行】
