网站、promise、跨域

1. 发布网站

1. 项目:前端后端开发的项目代码;
2. 域名:需要在万网(被阿里云收购)上购买域名;每个域名像身份证号一样,不会重复,一旦被注册,就不能进行再次购买;-->解析-->备案

  • DNS 解析;让当前域名和服务器的IP地址进行绑定;

3. 服务器:每个服务器都会有一个对应的IP地址;会把项目部署到服务器上;

  • 虚拟服务器;-->一般用于小型项目和小型公司的网站

4. ftp : 可以把项目上传到服务器;特定的端口下;

5. 【端口号】在服务器上分布这65535个小房间;一个服务器最多承载65535个项目;端口号的范围 0-65535;

  • 一般情况下,一个端口只配置一个项目;如果有两个项目,就会出现端口的占用;一个端口只能监听一个项目

2. http协议

  1. http : 超文本传输协议;在客户端和服务器之间不仅可以进行文本的传输,还可以传送图片,视频,音频; 是浏览器和服务端之间的约定好的一种规范;
  2. https : 加密的传输协议; 更安全,在协议加了一层密码,不容易被攻击;像银行,支付宝,政府等一般使用这类协议;
  3. http : 运行在客户端和服务器之间的快递小哥;可以把客户端信息传送给服务器;服务器可以整理好的数据通过http 再发送给客户端;

3. 在浏览器中输入一个url,都发生了什么?

1. http请求阶段

  1. 浏览器首先会把url 发送给DNS服务器;解析出一个服务器的IP地址;
  2. DNS服务器会根据IP找到对应的服务器,(服务器需要联网);
  3. 服务器接收到请求;客户端和服务器已经产生了链接;

2. http响应阶段

  1. 服务器接收到请求后,会根据你传过来的地址,路径等找到对应的项目;
  2. 在服务器找到之后,服务器立即把一些响应信息放在响应头,通过http发送给客户端;同时进行数据的整理;
  3. 把整理出来的数据,通过http发送给客户端;直到客户端数据接收完毕

3. 浏览器渲染阶段

  1. 浏览器拿到从服务器传输过来的文件;
  2. 首先会遍历HTML,形成DOM树;
  3. 代码从上到下解析,形成css树;
  4. DOM树和css树,重新组合成render树;
  5. 浏览器进行描绘和渲染;

4. 框架和jquery的区别

  1. 框架:组件化开发、虚拟DOM;操作的不是真实的DOM;
  2. jquery :操作的是真实的DOM,性能慢,比较低;

5. 三次握手;四次挥手

  1. 第一次握手: 客户端发送SYN码数据包发送给服务器,客户端要求和服务器建立联机;
  2. 第二次握手:服务端接收联机请求,会发送ACK码到客户端,是要建立联机吗;
  3. 第三次握手:客户端接收到服务端的ack码,验证是否正确,如果正确,则再次发送ack ,建立连接;

三次握手之后,客户端和服务端联机成功,可以发送数据
客户端和服务端发送数据是双向的;客户端给服务端传递的是路径,参数,随机数;服务端给客户端传输自己的资源,文件,数据;

  1. 第一次挥手,当客户端发送数据结束,需要发送fin告诉服务端,数据传输结束;
  2. 第二次挥手,当服务端数据接收完毕,服务端返回给客户端一个ACK码,;客户端接收到ack,就会把发送到服务端的通道进行关闭;
  3. 第三次挥手,服务端数据传输结束之后,也会发送fin给客户端;
  4. 第四次挥手,当客户端接收数据完毕之后,会发送给Ack给服务端,服务器可以安心关闭传输数据的通道;

6. uri、url、urn

  1. uri=url+urn

URI : 统一资源标识符
URL : 统一资源定位符
URN : 统一资源名称

  1. 由什么组成?

http : 传输协议; 如果是http协议,网站可以进行省略;
域名: image.baidu.com
端口号: 0--65535
路径 : 服务器的资源的文件的路径;
? : 问号后面跟着的是参数;?tn=属性值
? 后面常跟着一个随机的数字; 为了防止浏览器的缓存,不同的随机数,会重新进行请求

7. 接口文档

  1. 接口文档:前后交互的文档: 用来标识请求的url,参数,返回的数据类型;

url:"";
type:"get" "post";
参数 : username:""; password:"";

返回的数据类型: [{id:"",title:"",link:""},{},{}];
一般前端后端对项目一起进行开发,但是前端需要一些假数据来测试一下,所以就有了模拟数据和假数据;

8. ajax的基础

1. ajax : async javascript and xml;

xml:可扩展的标记语言;一般用于后台来存储数据的;

2. ajax的特点:只让页面的某个部分发生变化;
3. ajax的使用:

//ajax的使用

//1. 创建一个ajax实例
let xhr = new XMLHttpRequest();
//2. 打开一个路径;请求数据 xhr.open(get/post,url,false);
xhr.open("get",'aside1.json',true);//false 同步   true 异步;
//3. 监听: 当前ajax实例的属性readyState;当readyState发生变化,触发绑定的函数;
    // 0 :  初始化一个ajax的实例,readyState默认值是0;
    // 1 :  当open执行完毕之后,readyState的值是1;
    // 2 : 客户端已经接收到服务器返回的响应头;
    // 3 : 客户端开始接收数据,服务器在处理整理数据;
    // 4 : 客户端已经成功接收到所有的数据;
xhr.onreadystatechange = function () {// 当readyState发生变化,就会触发;
        console.log(this);// 指向了ajax的实例;
        console.log(xhr.readyState);// 2    3   4;
        if(xhr.readyState===4&& /^2\d{2}/.test(xhr.status)){
            // 说明浏览器已经成功获取到数据;
        }
    };
    
//4. 发送请求
xhr.send();

9. ajax的请求方式以及返回的状态码;

  1. ajax的请求方式;

1. get :一般用于获取服务器数据;

  • get请求传参数,需要把参数放在url问号的后面;
  • 浏览器对url的长度的有要求,IE 2K;谷歌8K;如果多余的,自动截取;
  • get请求安全性较低;(传输的数据会暴露在url的问号后面);
  • get 会有缓存;会在url 的后面拼接一个时间戳;(就是为了不走缓存);

2. post: 一般用于向服务器发送数据;

  • post 请求把参数放在请求体中发送给服务器;
  • 对于数据的大小没有限制;
  • post是比较安全;
  • post 没有缓存;

3. put : 向服务器发送一些数据;

4. delete: 向服务器删除数据

5. head: 只请求数据的响应头信息;

  1. 常用的状态码:
  • 200 : 客户端数据接收成功;
  • 301 : 永久重定向;
  • 302 :临时转移,临时重定向
  • 304 : 读取缓存;(浏览器缓存)
  • 307 : 临时转移’;
  • 401 : 没有权限访问该网站;
  • 404 : 路径错误;
  • 500 : 服务器未知错误;
  • 503 : 超负荷;访问量大;
//1. 
 let xhr = new XMLHttpRequest();
 
 xhr.open("get",'aside.json',true);
 
 xhr.onreadystatechange = function () {
        
        if (xhr.readyState === 4 && /^2\d{2}/.test(xhr.status)) {
            // 说明浏览器已经成功获取到数据;
            console.log(xhr.responseText);
        }
        // xhr.status; 状态码;代表当前请求的状态;
        // 当创建好实例,status默认状态值是0;
        // 当请求结束之后,会根据当前的请求状态去改变这个属性值;
        // 常用的状态码
        // 200 : 客户端数据接收成功
        // 301 : 永久重定向;
        // 302 :临时转移,临时重定向
        // 304 : 读取缓存;(浏览器缓存)
        // 307 : 临时转移
        // 401 : 没有权限访问该网站;
        // 404 : 路径错误
        // 500 : 服务器未知错误;
        // 503 : 超负荷;访问量大;
    }
    
    xhr.send();

10. ajax的同步异步

  1. js:单线程;每次执行一个任务;

当主任务队列执行完毕,再去把等待任务队列的任务拿到主任务队列来执行;(微任务,宏任务;)

  1. 浏览器:多线程;可以同时进行多个任务;
  2. 同步:浏览器必须把这个任务执行完毕,才能继续执行下一个任务;
  3. 浏览器让任务没有执行完,但是可以继续执行下一行代码;
  4. 异步的有:定时器、 ajax 、promise的then 、事件行为绑定的方法、 回调函数、async await
 let xhr = new XMLHttpRequest();
 
 xhr.open("get",'aside.json',true);//同步
    
 xhr.onreadystatechange = function () {
        console.log(xhr.readyState);//如果是异步请求,会执行三次,如果是同步请求会执行一次;
        if (xhr.readyState === 4 && /^2\d{2}/.test(xhr1.status)) {
            console.log(xhr.responseText);
        }
    };
    xhr1.send();

11. jQuery版ajax

$.ajax({
         url:"aside.json",
         type:"get",// 默认是get请求
         async:true,// 默认是异步
         data:{//向服务端发送的数据
             username:"1833333",
             password:"888888"
         },
         dataType:"json",// 默认请求回来是json格式;
         success:function (data) {
             // 数据请求成功执行这个回调
         },
         error:function(){
         //数据请求不成功执行这个回调
         }
     });


    // url : 请求路径
    // type:请求方式
    // dataType:返回的数据类型;
    // async : true: 异步(默认就是异步);
    // data: 属性值是一个对象;里面含有了多个键值对;客户端发送给服务器的参数;
    // success:当数据请求成功之后,调用success的回调函数;并且会把请求到的数据传给这个回调函数;
    // error: 当请求失败会执行这个回调函数;
    // cache:是否走缓存;true是走缓存,false,不走缓存;get;

1. Promise

  1. Promise:是浏览器新增的内置API;为了处理异步操作;
  2. Promise:是一个同步的过程;Promise传进的回调函数会立即执行;当回调函数执行完毕,才会执行下面的任务;
  3. Promise执行必须接收函数作为实参;
  4. Primise的三种状态:pending fulfilled rejected;从pending到成功状态、从pending到失败状态;如果当前promise状态一旦发生改变,那当前promise的状态就会凝固,不会发生改变
// promise的特点
// promise 是一个内置的类;不仅在window中存在,而且在node的global的全局对象下也存在;
// Promise 是es6新增的内置API;在IE下是不兼容;但是上线时会把所有es6的语法转换成es5;
/*for(var i=0;i<19;i++){
    // 闭包
    // 1.保护变量
    // 2.储存值
}*/

// 1.promise是同步的;传进一个回调函数;当执行promise时,会立即执行这个回调函数;

// 2. promise 有三个状态;
// pending  等待状态
// fulfilled   成功态
// rejected   失败态
// 一旦当前状态发生改变,当前状态凝固;resolve是从pending到fulfilled时触发的;rejected是pending到rejected触发;

// 3. resolve和reject传参的问题;

// 4.如果在Promise的回调函数中,抛出异常;会触发rejected中的所有函数;

// then  :
// 1.在promise原型的then方法中,返回是一个实例;实现then的链式调用;
// 2. 下一个then中执行fulfilled中方法,还是rejected 的方法;需要靠上一个then中返回的promise实例的状态;
// 3. 如果then中方法返回一个promise实例,那么这个promise会控制下一个then中方法执行;会把then默认返回的promise覆盖;
// 4. 如果then中没有相应的方法,那么会默认进行补全;
class  Mypromise{
    constructor(excutor){// constructor 接收到一个函数
        // this --->实例;
        // 当resolve执行时,会把当前实例上的成功的池子中所有的方法执行
        // 给实例初始化两个空数组;
        // 初始化一个状态,pending
        this.state = "pending";
        this.fulfilledEvent = [];
        this.rejectedEvent = [];
        this.value = undefined;
        let  resolve =result=>{
            // 循环池子中方法,让其挨个执行;
            // 定时器解决了then方法中函数的异步回调问题;
            // 一旦当前状态凝固,不能再次调用resolve状态;
            if(this.state!=="pending")return;
            this.state = "fulfilled";
            this.value  = result;
            setTimeout(()=>{
                this.fulfilledEvent.forEach(item=>{
                    if(typeof item==="function"){
                        item(this.value);
                    }
                })
            },0);
        };
        // 当reject执行时,会把实例上失败的池子方法执行;
        let reject =(reason)=>{
            if(this.state!=="pending")return;
            this.state = "rejected";
            this.value = reason;
            let timer = setTimeout(()=>{
                clearTimeout(timer);
                this.rejectedEvent.forEach(item=>{
                    if(typeof item==="function"){
                        item(this.value);
                    }
                });
            },0)
        };
        // 处理promise中的异常;
        try{
            excutor(resolve,reject);
        }catch (err){
            console.log(err);
            reject(err);
        }
    }
    // then方法,把成功或失败后的回调放进相应的池子中;
    then(resolveFn,rejectFn){
        // 如果then中,没有传递相应的方法,应对其进行补全;
        if(resolveFn==undefined){
            resolveFn = result =>{
                return result;
            }
        }
        if(rejectFn==undefined){
            rejectFn = reason =>{
               throw new Error('err');
                //为了执行下面的reject,在这个函数中抛出一个异常
            }
        }
        return new Mypromise((resolve,reject)=>{// 、
            //不能直接把函数放进去,因为需要判断当前函数是否返回一个promise的实例;
            this.fulfilledEvent.push(result=>{
                // 通过函数的返回值,是否是一个promise的实例,执行不同的方法;如果是promise实例,应该
                try{
                    let x = resolveFn(result);
                    x instanceof Mypromise?x.then(resolve,reject) : resolve(result);
                }catch(err){
                    reject(err);
                }
            });
            this.rejectedEvent.push(reason=>{
                // 通过函数的返回值,是否是一个promise的实例,执行不同的方法;如果是promise实例,应该
                try{
                    let x = rejectFn(reason);
                    x instanceof Mypromise?x.then(resolve,reject) : resolve(reason);
                    // 如果不是promise实例,执行下一个then中resolve;
                }catch(err){
                    reject(err)
                }
            });
        })
    }
}
new  Mypromise((resolve,reject)=>{
    console.log(1);
    //throw new  Error("你你");
    reject();
}).then(function (data) {
    console.log(2);
},function (data) {
    //console.log(data);
    console.log(3);
}).then(function () {
    console.log(4);
},function(){
    console.log(5);
});
console.log(6);

let p1 = new Promise(function (reslove,reject) {
        // 当Promise的回调函数中异步成功之后,执行特定的函数;
        // 当前函数中,存放的是异步的操作任务;当异步的操作任务成功之后,会调用then方法中的第一个函数;如果异步操作失败,会默认调用then的第二个函数;
        // resolve: 当异步操作成功,执行的函数;事件队列;收集了then方法中传进来的第一个参数;
        // reject : 当异步操作失败执行的函数;事件队列;收集了then方法中传进来的第二个参数;
        // 如果then方法中没有返回值,或者返回的不是一个promise的实例,那么下一个then中的函数会根据第一个异步的操作成功resolve执行有关;如果then的成功的回调中,如果then的第一个函数返回一个promise的实例,那么下一个then的第一个参数会根据上一个then的返回promise中异步操作成功后,会进行调用这个then的resolve;
        setTimeout(function () {
            reslove();
        },1000);
        console.log(1);
    });
 p1.then(function () {
        console.log("下课");
        return  new Promise(function (resolve,reject) {//重新生成一个promise实例;下面的then会根据这的promise实例来执行;
            setTimeout(function () {
                resolve();
            },3000)
        });
    }).then(function () {
        console.log(100);//他会根据上面那个promise实例里的那个定时器来执行(所以会延时3秒之后再执行)
    },function () {
        console.log(200);
    });

2. Promise的应用

1. promise:解决的是异步的回调地域;

  1. 如果有两个请求,第二个请求需要在第一个请求成功之后,再进行发送;
let  p = new Promise(function (resolve,reject) {
         $.ajax({
            url:"aside.json",
            dataType:"json",
            success:function () {
                resolve();
            }
         })
    });
    p.then(function () {
        $.ajax({
            url:"banner.json",
            dataType:"json",
            success:function () {

            }
        })
    });

//把代码封装优化如下

function queryFn(url) {//函数每执行一次就会创建一个primise实例
        return new Promise(function (resolve,reject) {
            $.ajax({
                url:url,
                dataType:"json",
                success:function () {
                    resolve();
                }
            });
        });
    }
    
    queryFn("aside.json").then(function () {//如果不写return,这个回调函数的返回值就是undefined;只有promise的实例才能调用then
     return  queryFn("banner.json");
    }).then(function () {
        queryFn("111.json")
    });
  // then : 可以只传一个参数;那么这个参数是成功的回调;

3. Promise中的catch

let p1 = new Promise(function (resolve,reject) {
        setTimeout(function () {
            if(Math.random()>0.5){
                resolve(12)
            }else{
                reject()
            }
        },1000)
    });
    // 一般情况下,then只放一个成功的回调函数,会把失败的回调函数放进catch的回调函数
    p1.then(function (data) {
        console.log(data);
        return new Promise(function (resolve,reject) {
            reject();
        })
    }).then(function () {

    }).catch(function () {//把catch放到最后,只要有一个请求失败,就会执行catch;
        console.log(13);
    })

4. Promise.all和Promise.race

Promise.all

  1. Promise.all返回一个新的promise的实例;这个新的实例的状态由数组中的promise实例来决定,当数组中所有的promise都是成功态,新的promise就是成功态,如果有一个失败,变成失败态;
  2. 数组中的promise实例,会把成功的数据组成一个数组,传给promise.all的then的参数;

Promise.race

  1. 数组中的实例谁先执行,那么就会把谁的数据传递给then;
function queryFn(url) {
        return new Promise(function (resolve,reject) {
            $.ajax({
                url:url,
                dataType:"json",
                success:function (data) {
                    resolve(data);
                }
            });
        });
    }

//1. promise.all
//当数组中的所有实例都执行成功,then才会执行
 Promise.all([queryFn('aside.json'),queryFn("banner.json")]).then(function (arr) {//传参是数组形式的
    console.log(arr);
    }).catch(function (a) {
        console.log(a);
    });

//2. promise.race
//数组中的哪个实例请求的快,then输出哪个
 Promise.race([queryFn('aside.json'),queryFn("banner.json")]).then(function (arr) {
        console.log(arr);
    }).catch(function (a) {
        console.log(a);
    });

5. 异步的微任务(async)和宏任务

  1. 主任务队列存储的都是同步的任务;
  2. 等待任务队列中存储都是异步的任务;当主任务队列中的任务执行完成之后,接下来会把异步任务队列到达时间的任务拿出放到主任务队列中进行执行;

在异步的任务队列中分为微任务宏任务;当同步的任务执行完毕,先去等待的任务队列把所有的微任务找出来,挨个执行;当微任务执行完毕,再把所有的宏任务执行;

  1. 微任务: Promise的then 、 async函数、 process.nextTick
  2. 宏任务:setTimeout 、 setInterval ...
  3. async
  4. .async这个函数默认返回一个promise的实例;返回值可以调用then方法
  5. 在函数中await后面的代码都是异步的;把后面的表达式变成一个微任务;
  6. async必须成对出现(和await一起出现)
function fn() {
        console.log(3);
    };
    
async function sum() {
        console.log(1);
        await fn();
        // await : 把后面的代码变成了异步的任务;
        console.log(2);
    }
    sum();
    console.log(4);
    
//输出 1 3 4 2

6. 跨预(jsonp)

  1. 跨预存在同源策略和非同源策略

同源:协议相同、域名相同、端口号相同

  1. ajax属于同源策略,在不做任何处理的情况下,只能访问自己服务器下的数据
  2. 浏览器属于非同源策略,可以访问任何服务器上的数据;
  3. script标签里的src属性是非同源策略,发送的请求可以跨预拿到数据,
  4. JSONP是常见的一种跨域解决方式,实现非同源下的数据请求;




  1. jsonp的原理:
  1. 利用script标签的src属性,src属性是非同源策略,可以访问不同服务器或端口下的数据
  2. 给这个src的路径拼接一个callback的属性,callback=fn;当数据通过http传输给服务器;服务器会把数据放进callback传进的函数的参数里
  3. 服务器把处理的数据和函数通过http传给客户端,当客户端接收到之后,让fn进行执行
    fn(data);

你可能感兴趣的